我正在开发一个将文件从一个位置复制到另一个位置的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属性),并将它们与最终目标中的文件进行比较。 这也应该没问题,因为文件大小只会增加,因为文本只是添加。
我看了很多人推荐FileSystemWatcher,但我不想错过可能发生的一些变化 - 至少我在其他SO问题上读过这些变化(见https://stackoverflow.com/a/240008/2296407)。
在最后x分钟或秒内知道任何文件是否被更改(如果源中的文件与最终目标中的文件不同)的最佳选项是什么?因为可能有很多因为我不想复制所有内容的文件。
作为最佳选择,我的意思是:比较每个文件大小或将File.GetLastWriteTime(myFile)
与实际时间 - 一段时间进行比较是否更快。在第二种情况下,还有一个问题:时间跨度应该有多大?如果我把时间跨度很大,我可能会复制比我实际需要的文件更多的文件,但如果我把它放低,我可能会错过一些更改。
如果您有更好的选择,请随时与我分享!
答案 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);
}