如何使用 FileSystemWatcher 同步两个文件夹操作

How to use FileSystemWatcher for synchronizing two folders action's

那么,我有一个任务:
2个目录内容实时同步
给定 2 个目录的路径,侦听目录 1 中的更改并将操作与 dir2.This 同步意味着当我在目录 1 中创建一个新文件时,相同的文件应该在目录 2 中,当我删除或修改时也会发生同样的情况file.Dir1 可能有嵌套文件夹。
我有这个起点:

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}";
        Console.WriteLine(value);
    }

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

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

    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);
        }
    }
}   

onCreated 事件中我添加了这一行:
File.Copy(e.FullPath, 目的地);

如果文件位于主目录中,它会创建该文件,但如果它位于嵌套文件夹中,则会引发错误。然后我尝试在事件中添加此代码:

FileInfo destFile = new FileInfo(destinationFolder + srcFile.FullName.Replace(sourceFolder, ""));

if (!Directory.Exists(destFile.DirectoryName) && createFolders)
{
    Directory.CreateDirectory(destFile.DirectoryName);
}

//Check if src file was modified and modify the destination file
if (srcFile.LastWriteTime > destFile.LastWriteTime || !destFile.Exists)
{
    File.Copy(srcFile.FullName, destFile.FullName, true);
} 

另外,没用。我应该怎么做才能完成这项任务?我正在学习 C#,我不知道所有的细节,在此先感谢!

我已经完成了这个任务,但是在这个程序中仍然存在一个小问题,当我尝试在 dir1 中创建一个子文件夹时,它给出了未经授权的异常,我无法访问子文件夹路径,我想我把它们结合起来不是很好,但我不知道如何修复 it.Now,该程序在 dir2 中镜像了 dir1 中的操作,没有子文件夹。

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.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;
        }
        string destinationPath = @"C:\Users\artio\Desktop\FASassignment\root\dir2";
        var fullPath = e.FullPath;
        var name = e?.Name;
        string destination = Path.Combine(destinationPath, name);
        File.Copy(fullPath, destination, true);
        Console.WriteLine($"Changed: {e.FullPath}");
    }

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

        var Destination = @"C:\Users\artio\Desktop\FASassignment\root\dir2";
        var name = e.Name;
        var fullPath = e.FullPath;
        string destination = Path.Combine(Destination, name);
        Console.WriteLine($"Copy to: {destination}");
        Thread.Sleep(1000);
        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)
    {
        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 Destination = @"C:\Users\artio\Desktop\FASassignment\root\dir2";
        var oldDestinationPath = Path.Combine(Destination, oldFileName);
        var newDestinationPath = Path.Combine(Destination, newFileName);
        var info = new FileInfo(oldDestinationPath);
        info.MoveTo(newDestinationPath);
    }

    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);
        }
    }
}