在 C# 中不断读取自上次检查以来没有 运行 程序的文件更改

Read file changes since the last check without running program constantly in C#

我正在尝试创建一个简单的文件监视器,它会定期检查日志文件中的更新并处理更新。我尝试使用 FileSystemWatcher,但这需要 我的应用程序永远保持 运行。我更多地考虑读取更改、退出、等待计时器、再次读取更改。

我创建了一个定期运行的服务来读取文件并获取全部数据。下面是简单的代码。

private void SchedularCallback(object e)
{
    string logFile = ReadFromFile("C:\test.log");
    this.WriteToFile(logFile);
    this.ScheduleService();
}

WriteToFile 函数将数据写入一个单独的文件(过程数据,实际过程可能涉及其他任务,如调用 WCF 服务、检查互联网访问等)。每次回调发生时,ReadFromFile 都会读取日志文件。下面是读取文件的代码。

private string ReadFromFile(string path)
{
    try
    {
        string logs = "";
        using (StreamReader reader = new StreamReader(path, true))
        {
            logs = reader.ReadToEnd();
            reader.Close();
        }

        return logs;
    }
    catch (Exception ex)
    {
        WriteToFile("Simple Service Error on: {0} " + ex.Message + ex.StackTrace);

        //Stop the Windows Service.
        using (System.ServiceProcess.ServiceController serviceController = new System.ServiceProcess.ServiceController("SimpleService"))
        {
           serviceController.Stop();
        }
        return "";
    }
}

如您所见,每次回调发生时,这段代码都会读取整个文件。由于日志文件最终可能会非常大,因此不可能每次都读取和处理整个文件。为了改善这一点,我想到了使用 FileSystemWatcher,但这将使我的服务 运行 永远保持下去,并且会成为真正的性能消耗。相反,如果我只能读取文件中的更改,它会更快。

我还考虑过存储流式编写器的最后一个偏移量,但这只有在附加数据时才有效。如果有人删除了整个日志或更改了一两行,最后的偏移量将不起作用。

在这种情况下,最好的方法是什么。日志文件显然不会经常变化,所以我不需要保留我的服务运行。我不确定二进制流然后与最后一个二进制流进行比较是否是个好主意。对可能方法的任何建议表示赞赏。基本上类似于 git 所做的识别自上次提交以来的更改,这就是我正在寻找的。

谢谢。

查看 NTFS 的 USN Journal

它基本上记录了对 NTFS 磁盘上文件的所有更改。

以下是一些可能有用的链接:

  1. Creating, Modifying, and Deleting a Change Journal
  2. Fsutil usn
  3. File Path from USN Journal

这正是 FileSystemWatcher 的用武之地。只要是单个文件,资源使用就会最少。

更新: 事实上,轮询与监听 API/Kernel 的变化对于像日志这样的东西来说可能有点矫枉过正。搜索 log/journal 可能更好(假设它们已打开)。但是在 worst/most 可靠地,您可以使用自己的计时器系统来监视文件上的 Size+LastModifiedTime。使用 MD5 校验和也应该是 okay/fast.

然后如果有变化,你可以使用差异库来同步。例如diffplex.

如果您可以在这里测试并稍后对结果进行基准测试。这对我和其他用户来说真的很有帮助,因为我之前已经用 FileSystemWatcherEx.

实现了类似的东西