观察目录并处理复制的文件 - 检查复制完成和打开句柄

时间:2016-01-05 04:58:05

标签: c# .net file directory filesystemwatcher

我需要查看图像文件的目录(jpeg,png,tif,gif,bmp)并处理放置在那里的新文件。我试图使用FileSystemWatcher来实现它

private void watch()
{
  FileSystemWatcher watcher = new FileSystemWatcher();
  watcher.Path = path;
  watcher.Filter = "*.*";
  watcher.Changed += new FileSystemEventHandler(OnChanged);
  watcher.EnableRaisingEvents = true;
}

但是我如何确保文件被完整复制并且在尝试打开文件之前没有锁定文件的句柄?

2 个答案:

答案 0 :(得分:1)

要在文件完全复制后处理文件,您需要添加以下过滤器:

watcher.NotifyFilter = NotifyFilters.LastWrite;

一旦文件完全复制到目录

,这将通知

参考:FileSystemWatcher

对于多文件过滤器,您有两种选择:

watcher.Filter = "*.*";

或使用以下构造函数:

FileSystemWatcher watcher = new FileSystemWatcher("path","*.*");

答案 1 :(得分:0)

知道文件是否完全复制的唯一进程是进行复制的进程。想一想 - 文件只是一个数据流。没有其他信息,就无法知道文件中应该有多少数据。

如果没有某种形式的通信,文件被完全复制,任何其他进程唯一能做的就是根据文件未打开而不再被写入进行猜测,然后希望猜测是正确的。依赖于文件不再被写入或任何其他进程保持打开的任何此类操作都无法处理故障。如果某个文件正在被FTP等进程复制,并且网络连接因为任何原因而在复制文件的过程中丢失,那就是猜测并希望"进程将错误地将文件标识为已完成。

有几种方法可以解决这个问题,但它们都要求发送过程向接收器发送某种类型的信号,以便文件完成。

您可以让发送过程发送" DONE" file - 在发送DataFile之后,发送过程然后发送一个名为DataFile.done的零长度文件。看到DataFile.done后,您确定DataFile已完全复制。如果您没有看到DataFile.done,则DataFile不会被完全复制。

如果底层操作系统和文件系统支持原子文件重命名操作,您也可以让发送过程重命名该文件。您可以让您的发送过程最初发送DataFile.copying,并在复制完成后将文件重命名为DataFile。任何具有.copying扩展名的文件仍在复制过程中。

某些数据文件格式也表示完整文件。 PDF文件遵循指定的格式,您可以判断它们是否已完成。 XML文件的构建方式可以让您知道它们是否完整。但这不是一个有效的解决方案,因为它需要解析文件的内容,如果文件很大或有性能要求,多次连续读取每个文件都会导致严重的IO性能问题。

同样,如果没有发送过程发送某种DONE标志,您就无法解决此问题。接收过程根本没有足够的数据来做除文件完成时猜测之外的任何事情,然后它只能希望它做出正确的猜测。

依赖猜测和希望的系统通常不是非常可靠。