文件系统观察器 - 不仅观察文件而且观察内部文件

Posted

技术标签:

【中文标题】文件系统观察器 - 不仅观察文件而且观察内部文件【英文标题】:File System Watcher - watch not only file but also inside file 【发布时间】:2022-01-13 08:01:25 【问题描述】:

如何使用 FileSystemWatcher 监控文件中的更改

我有一个包含疾病的文件夹,我想在控制台上不仅显示包中的更改,还显示文件(例如 .txt .doc ...)中的更改 我使用事件(创建删除更改),但它仅适用于文件夹,不适用于文件内

【问题讨论】:

所以你想做某种文件差异? 它只适用于文件夹,而不适用于文件内部 - 但编辑文件的最后写入时间会发生变化,FSW 会选择它.. ? FSW 不会告诉您文件内部发生了哪些更改,只会告诉您文件已更改。要么自己保留文件的副本,并在每次看到更改时对其进行比较.. 或者使用 git 之类的东西来查看更改 @TheGeneral 我想输出到控制台,例如(文件中的文本现在写入)更改(现在不写入文本)并且此更改专用并输出 @CaiusJard 不能将文件中的变化实时显示到控制台吗?? 【参考方案1】:

您可以从文件中获取副本作为历史回购,并在需要时从中获取旧内容

来自original example的修改示例

class MyClassCS


    static HelperRepo repo;
    static void Main()
    
        string SrcDir = @"D:\XRep";
        using var watcher = new FileSystemWatcher(SrcDir);
        repo = new HelperRepo(SrcDir); // repo for history changes


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



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

        watcher.Filter = "*.txt";
        watcher.IncludeSubdirectories = true;
        watcher.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");
        // you can see the diff from your repo 

        var oldContent = repo.GetFileContent(e.FullPath);
        var newContet = File.ReadAllText(e.FullPath);
        Console.WriteLine($"new Content : newContet");
        Console.WriteLine($"old Content: oldContent");

        // reflect change in repo
        repo.ReflectFile(e.FullPath);


    

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

        // reflect change in repo
        repo.ReflectFile(e.FullPath);

    

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

        // reflect change in repo
        repo.ReflectDelet(e.FullPath);
    

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

        // reflect change in repo
        repo.ReflectRename(e.OldFullPath, 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);
        
    



HelperRepo

class HelperRepo

    private readonly string _repoDir = @"D:\temp_repo";
    private readonly string _srcDir;

    public HelperRepo(string srcDir)
    
        Directory.CreateDirectory(srcDir); // make sure that repo exist
        CopyFilesRecursively(srcDir, _repoDir);
        _srcDir = srcDir;
    

    public string GetFileContent(string src_File)
    
        var dir = Path.GetDirectoryName(src_File) ?? "";
        if (!dir.StartsWith(_srcDir))
            throw new ArgumentException("inCorect Directory");
        var repoFile = src_File.Replace(_srcDir, _repoDir);
        return File.ReadAllText(repoFile);
    

    public void ReflectFile(string src_File)
    
        var dir = Path.GetDirectoryName(src_File) ?? "";
        if (!dir.StartsWith(_srcDir))
            throw new ArgumentException("inCorect Directory");

        File.Copy(src_File, src_File.Replace(_srcDir, _repoDir), true);
    

    public void ReflectDelet(string src_File)
    
        var dir = Path.GetDirectoryName(src_File) ?? "";
        if (!dir.StartsWith(_srcDir))
            throw new ArgumentException("inCorect Directory");

        File.Delete(src_File.Replace(_srcDir, _repoDir));
    

    public void ReflectRename(string oldPath, string newPath)
    
        ReflectDelet(oldPath);
        ReflectFile(newPath);
    

    static void CopyFilesRecursively(string sourcePath, string targetPath)
    
        //Now Create all of the directories
        foreach (string dirPath in Directory.GetDirectories(sourcePath, "*", SearchOption.AllDirectories))
        
            Directory.CreateDirectory(dirPath.Replace(sourcePath, targetPath));
        

        //Copy all the files & Replaces any files with the same name
        foreach (string srcFile in Directory.GetFiles(sourcePath, "*.*", SearchOption.AllDirectories))
        
            var targetFile = srcFile.Replace(sourcePath, targetPath);
            File.Copy(srcFile, targetFile, true);
        
    


【讨论】:

以上是关于文件系统观察器 - 不仅观察文件而且观察内部文件的主要内容,如果未能解决你的问题,请参考以下文章

带有 Flutter 框架的文件观察器

创建文件观察器,当特定文件被修改时将重新启动 websocket 服务器

在 JetBrains WebStorm 中使用 node.js 文件观察器

xml XO文件观察器

如何使用 C# 在文件观察器中捕获剪切和粘贴操作

markdown Dockerfile的IntelliJ IDEA文件观察器设置