无法访问该文件,因为该文件正在使用中

发布于 2025-01-11 06:01:52 字数 3773 浏览 0 评论 0原文

我需要使用 FileSystemWatcher 将操作从 dir1 同步到 dir2。当我在 dir1 中创建新文件时,相同的文件必须在 dir2 中,如果我删除/重命名/移动,也应该在 dir2 中。
当我在 dir1 中创建文件时,它也在 dir2 中创建,但是当我尝试重命名 dir1 中的文件时,我收到此异常:未处理的异常。 System.IO.IOException:该进程无法访问文件“C:\ Users \ artio \ Desktop \ FASassignment \ root \ dir1 \ g.txt”,因为它正在被另一个进程使用。当我用谷歌搜索时,这由于流未关闭,可能会出现错误,但我不知道我是否使用该流。另外,当我在其中创建子文件夹和文件时,我收到一条错误消息,指出未找到路径并且在 dir2 中未创建路径,您能帮我解决这两个错误吗?预先感谢!
程序:

public class Program2
{
    public static void Main(string[] args)
    {
        string sourcePath = @"C:\Users\artio\Desktop\FASassignment\root\dir1";
        string destinationPath = @"C:\Users\artio\Desktop\FASassignment\root\dir2";

        var source = new DirectoryInfo(sourcePath);
        var destination = new DirectoryInfo(destinationPath);

        using var sourceWatcher = new FileSystemWatcher(sourcePath);

        sourceWatcher.NotifyFilter = NotifyFilters.Attributes
                             | NotifyFilters.CreationTime
                             | NotifyFilters.DirectoryName
                             | NotifyFilters.FileName
                             | NotifyFilters.LastAccess
                             | NotifyFilters.LastWrite
                             | NotifyFilters.Security
                             | NotifyFilters.Size;

        sourceWatcher.Changed += OnChanged;
        sourceWatcher.Created += OnCreated;
        sourceWatcher.Deleted += OnDeleted;
        sourceWatcher.Renamed += OnRenamed;
        sourceWatcher.Error += OnError;

        sourceWatcher.Filter = "*.txt";
        sourceWatcher.IncludeSubdirectories = true;
        sourceWatcher.EnableRaisingEvents = true;

        Console.WriteLine("Press enter to exit.");
        Console.ReadLine();
    }

    private static void OnChanged(object sender, FileSystemEventArgs e)
    {
        if (e.ChangeType != WatcherChangeTypes.Changed)
        {
            return;
        }

        Console.WriteLine($"Changed: {e.FullPath}");
    }

    private static void OnCreated(object sender, FileSystemEventArgs e)
    {
        string value = $"Created: {e.FullPath}";

        string destinationPath = @"C:\Users\artio\Desktop\FASassignment\root\dir2";
        var name = e.Name;
        var fullPath = e.FullPath;
        string destination = Path.Combine(destinationPath, name);
        File.Copy(fullPath, destination,true);

        Console.WriteLine(value);
    }

    private static void OnDeleted(object sender, FileSystemEventArgs e)
    {
        Console.WriteLine($"Deleted: {e.FullPath}");

        var name = e.Name;
        string destinationPath = @"C:\Users\artio\Desktop\FASassignment\root\dir2";
        string destination = Path.Combine(destinationPath, name);
        File.Delete(destination);
    }

    private static void OnRenamed(object sender, RenamedEventArgs e)
    {
        var oldFullPath = e.OldFullPath;
        var fullPath = e?.FullPath;
        Console.WriteLine($"Renamed:");
        Console.WriteLine($"    Old: {e.OldFullPath}");
        Console.WriteLine($"    New: {e.FullPath}");
        string destinationPath = @"C:\Users\artio\Desktop\FASassignment\root\dir2";

        string destination = Path.Combine(destinationPath, fullPath);
        File.Copy(fullPath, destination, true);
        File.Delete(oldFullPath);
    }

    private static void OnError(object sender, ErrorEventArgs e) =>
        PrintException(e.GetException());

    private static void PrintException(Exception? ex)
    {
        if (ex != null)
        {
            Console.WriteLine($"Message: {ex.Message}");
            Console.WriteLine("Stacktrace:");
            Console.WriteLine(ex.StackTrace);
            Console.WriteLine();
            PrintException(ex.InnerException);
        }
    }
}

I need to sync actions from dir1 to dir2 using FileSystemWatcher. When i create a new file in dir1,the same file must be in dir2,if i delete/rename/move,in dir2 should also.
When i create the file in dir1,it is being created in dir2 also,but when i try to rename the file in dir1,i get this exception : Unhandled exception. System.IO.IOException: The process cannot access the file 'C:\Users\artio\Desktop\FASassignment\root\dir1\g.txt' because it is being used by another process. As i googled,this error may appear because the stream isn't closed,but i dont know if i work with one. Also,when i create a subfolder and a file in it,i get an error that the path isnt found and in dir2 it doesnt create,could you help me please with these two errors? Thanks in advance!
Program:

public class Program2
{
    public static void Main(string[] args)
    {
        string sourcePath = @"C:\Users\artio\Desktop\FASassignment\root\dir1";
        string destinationPath = @"C:\Users\artio\Desktop\FASassignment\root\dir2";

        var source = new DirectoryInfo(sourcePath);
        var destination = new DirectoryInfo(destinationPath);

        using var sourceWatcher = new FileSystemWatcher(sourcePath);

        sourceWatcher.NotifyFilter = NotifyFilters.Attributes
                             | NotifyFilters.CreationTime
                             | NotifyFilters.DirectoryName
                             | NotifyFilters.FileName
                             | NotifyFilters.LastAccess
                             | NotifyFilters.LastWrite
                             | NotifyFilters.Security
                             | NotifyFilters.Size;

        sourceWatcher.Changed += OnChanged;
        sourceWatcher.Created += OnCreated;
        sourceWatcher.Deleted += OnDeleted;
        sourceWatcher.Renamed += OnRenamed;
        sourceWatcher.Error += OnError;

        sourceWatcher.Filter = "*.txt";
        sourceWatcher.IncludeSubdirectories = true;
        sourceWatcher.EnableRaisingEvents = true;

        Console.WriteLine("Press enter to exit.");
        Console.ReadLine();
    }

    private static void OnChanged(object sender, FileSystemEventArgs e)
    {
        if (e.ChangeType != WatcherChangeTypes.Changed)
        {
            return;
        }

        Console.WriteLine(
quot;Changed: {e.FullPath}");
    }

    private static void OnCreated(object sender, FileSystemEventArgs e)
    {
        string value = 
quot;Created: {e.FullPath}";

        string destinationPath = @"C:\Users\artio\Desktop\FASassignment\root\dir2";
        var name = e.Name;
        var fullPath = e.FullPath;
        string destination = Path.Combine(destinationPath, name);
        File.Copy(fullPath, destination,true);

        Console.WriteLine(value);
    }

    private static void OnDeleted(object sender, FileSystemEventArgs e)
    {
        Console.WriteLine(
quot;Deleted: {e.FullPath}");

        var name = e.Name;
        string destinationPath = @"C:\Users\artio\Desktop\FASassignment\root\dir2";
        string destination = Path.Combine(destinationPath, name);
        File.Delete(destination);
    }

    private static void OnRenamed(object sender, RenamedEventArgs e)
    {
        var oldFullPath = e.OldFullPath;
        var fullPath = e?.FullPath;
        Console.WriteLine(
quot;Renamed:");
        Console.WriteLine(
quot;    Old: {e.OldFullPath}");
        Console.WriteLine(
quot;    New: {e.FullPath}");
        string destinationPath = @"C:\Users\artio\Desktop\FASassignment\root\dir2";

        string destination = Path.Combine(destinationPath, fullPath);
        File.Copy(fullPath, destination, true);
        File.Delete(oldFullPath);
    }

    private static void OnError(object sender, ErrorEventArgs e) =>
        PrintException(e.GetException());

    private static void PrintException(Exception? ex)
    {
        if (ex != null)
        {
            Console.WriteLine(
quot;Message: {ex.Message}");
            Console.WriteLine("Stacktrace:");
            Console.WriteLine(ex.StackTrace);
            Console.WriteLine();
            PrintException(ex.InnerException);
        }
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

遗失的美好 2025-01-18 06:01:52

您的问题是这一行:

string destination = Path.Combine(destinationPath, fullPath);

调试它,您会发现这不会导致您的想法。您正在尝试合并两个完整路径。

相反,使用这个:

private void OnRenamed(object sender, RenamedEventArgs e)
{                       
    Console.WriteLine($"Renamed:");
    Console.WriteLine($"    Old: {e.OldFullPath}");
    Console.WriteLine($"    New: {e.FullPath}");

    var oldFileName = Path.GetFileName(e.OldFullPath);
    var newFileName = Path.GetFileName(e.FullPath);
    var oldDestinationPath = Path.Combine(Destination, oldFileName);
    var newDestinationPath = Path.Combine(Destination, newFileName);
    var info = new FileInfo(oldDestinationPath);            
    info.MoveTo(newDestinationPath);
}

注意我没有使用 File 类。众所周知这是有问题的。

另外,我建议使用某种进程日志并重试,以便您可以恢复。否则,这可能会留下大量更改,因为文件可能会保留这些更改,从而可能导致操作失败。

更新:

关于您有关附加文件的其他问题,看起来您正在尝试在创建该文件的进程释放该文件的句柄之前访问该文件,因此您可以尝试引入一个小的延迟一秒钟或其他什么:

private void OnCreated(object sender, FileSystemEventArgs e)
{
    var name = e.Name;
    var fullPath = e.FullPath;
    string destination = Path.Combine(Destination, name);
    Console.WriteLine($"Copy to: {destination}");
    Thread.Sleep(1000); //Intentional delay
    File.Copy(fullPath, destination, true);
    Console.WriteLine("File copied successfully.");
}

Your issue is this line:

string destination = Path.Combine(destinationPath, fullPath);

Debug it and you will see that this does not result in what you think. You are attempting to merge two full paths.

Instead, use this:

private void OnRenamed(object sender, RenamedEventArgs e)
{                       
    Console.WriteLine(
quot;Renamed:");
    Console.WriteLine(
quot;    Old: {e.OldFullPath}");
    Console.WriteLine(
quot;    New: {e.FullPath}");

    var oldFileName = Path.GetFileName(e.OldFullPath);
    var newFileName = Path.GetFileName(e.FullPath);
    var oldDestinationPath = Path.Combine(Destination, oldFileName);
    var newDestinationPath = Path.Combine(Destination, newFileName);
    var info = new FileInfo(oldDestinationPath);            
    info.MoveTo(newDestinationPath);
}

Note I am not using the File class. It's known to be problematic.

Also, I recommend using a process log of some sort and retries so you can recover. Otherwise, this has the potential to leave a lot of changes behind as files can have holds on them that may result in your operations failing.

UPDATE:

With regards to your other issue concerning additional files, it looks like you are trying to access the file before the process creating it has released the handle on it, so you can try introducing a small delay of a second or something:

private void OnCreated(object sender, FileSystemEventArgs e)
{
    var name = e.Name;
    var fullPath = e.FullPath;
    string destination = Path.Combine(Destination, name);
    Console.WriteLine(
quot;Copy to: {destination}");
    Thread.Sleep(1000); //Intentional delay
    File.Copy(fullPath, destination, true);
    Console.WriteLine("File copied successfully.");
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文