检查文件修改

时间:2014-07-16 10:56:06

标签: c# windows service filesize

我正在做什么

我正在开发一个将文件从一个位置复制到另一个位置的Web服务。文件正在更新(由于添加了文本,因此大小应该每3秒增加一次)。

第一个选项:

如果任何文件被修改(我们每隔5秒cca修改一次),我每10秒检查一次,这样我就可以将它们复制(并覆盖)到最终目的地。 Atm我正在使用一个代码,它将文件的最后编辑时间与实际时间进行比较 - 一段时间(1分钟atm)。

DateTime lastEditTime = new DateTime();
lastEditTime = File.GetLastWriteTime(myFile);

if (lastEditTime > DateTime.Now.AddMinutes(-1)) 
{
     File.Copy(myFile, newFileName, true);
}

但我认为这是一种不好的方法,因为可能有一些时间空间或某些东西,我不会得到一些改变。

第二个选项

我可以检查源目录中每个文件的文件大小(可能使用FileInfo.Length属性),并将它们与最终目标中的文件进行比较。 这也应该没问题,因为文件大小只会增加,因为文本只是添加。

第3个选项

我看了很多人推荐FileSystemWatcher,但我不想错过可能发生的一些变化 - 至少我在其他SO问题上读过这些变化(见https://stackoverflow.com/a/240008/2296407)。

我的问题是什么?

在最后x分钟或秒内知道任何文件是否被更改(如果源中的文件与最终目标中的文件不同)的最佳选项是什么?因为可能有很多因为我不想复制所有内容的文件。 作为最佳选择,我的意思是:比较每个文件大小或将File.GetLastWriteTime(myFile)与实际时间 - 一段时间进行比较是否更快。在第二种情况下,还有一个问题:时间跨度应该有多大?如果我把时间跨度很大,我可能会复制比我实际需要的文件更多的文件,但如果我把它放低,我可能会错过一些更改。

如果您有更好的选择,请随时与我分享!

1 个答案:

答案 0 :(得分:1)

虽然您已经在选项3中提到过,但我仍然认为应该尝试使用FileSystemWatcher Class。据我了解你,你还没有这样做,对吗?

虽然观察者确实可能会在默认配置中丢失某些事件,但如果您进行一些调整,仍然可以使其正常工作。

查看文档中的“备注”部分(由我突出显示):

  

Windows操作系统会通知组件文件更改   在FileSystemWatcher创建的缓冲区中。如果很多   在短时间内发生变化,缓冲区可能会溢出。这导致了   组件忘记跟踪目录中的更改,它只会   提供全面通知。增加缓冲区的大小   InternalBufferSize属性很昂贵,因为它来自   非分页内存,无法换出磁盘,所以保持   缓冲区虽小但足够大,不会错过任何文件更改事件。   为避免缓冲区溢出,使用NotifyFilter和   IncludeSubdirectories 属性,以便您可以过滤掉不需要的更改   通知。

你可以做的事情让它可靠地发挥作用:

  

请注意,FileSystemWatcher可能会在缓冲区大小时错过事件   超过了。为避免遗漏事件,请遵循以下准则:

     
      
  • 通过设置InternalBufferSize属性来增加缓冲区大小。
  •   
  • 避免观看具有长文件名的文件,因为长文件名有助于填充缓冲区。考虑重命名这些文件   使用较短的名字。
  •   
  • 尽可能缩短您的事件处理代码。
  •   

例如,用户 Nomix 表示他将缓冲区大小(属性InternalBufferSize)提升到16 MB并且从未遇到FileSystemWatcher类的问题(SO post { {3}}。)我可以通过我公司的一个项目证实这一点,该项目也可以使用多年,因为我们发现了缓冲区。

对象的初始化可能如下所示:

private void InitWatcher()
{
    // Create a new FileSystemWatcher and set its properties.
    FileSystemWatcher watcher = new FileSystemWatcher();
    watcher.Path = "Your path to watch";

    // You only want to watch a single folder
    watcher.IncludeSubdirectories = false;

    // You mentioned both LastWrite and Size
    // You can combine them or just watch for only a specific property
    // Simply configure it to your needs
    watcher.NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.Size

    // Only watch text files.
    watcher.Filter = "*.txt";

    // Add event handlers, omit those you are not interested in
    watcher.Changed += new FileSystemEventHandler(OnChanged);

    // Begin watching.
    watcher.EnableRaisingEvents = true;
}

然后,您可以订阅那些您感兴趣的事件,例如is here事件,并对其做出反应就像:

private static void OnChanged(object source, FileSystemEventArgs e)
{
   File.Copy(e.FullPath, newFileName, true);
}