文件系统观察程序和大文件

var fsw = new FileSystemWatcher(sPath, "*.PPF"); fsw.NotifyFilter = NotifyFilters.FileName; fsw.IncludeSubdirectories = true; fsw.Created += FswCreated; fsw.EnableRaisingEvents = true; static void FswCreated(object sender, FileSystemEventArgs e) { string sFile = e.FullPath; string[] arrLines = File.ReadAllLines(sFile); } 

这对于大文件失败,因为编写文件时没有完成该过程。 该文件是通过网络复制的,所以我不知道文件的大小。 需要什么样的同步才能使其稳健?

在stackoverflow上找到解决方案并对其进行了一些修改。

 static bool IsFileLocked(FileInfo file) { FileStream stream = null; try { stream = file.Open(FileMode.Open, FileAccess.ReadWrite, FileShare.None); } catch (IOException) { //the file is unavailable because it is: //still being written to //or being processed by another thread //or does not exist (has already been processed) return true; } finally { if (stream != null) stream.Close(); } //file is not locked return false; } static void FswCreated(object sender, FileSystemEventArgs e) { string sFile = e.FullPath; Console.WriteLine("processing file : " + sFile); // Wait if file is still open FileInfo fileInfo = new FileInfo(sFile); while(IsFileLocked(fileInfo)) { Thread.Sleep(500); } string[] arrLines = File.ReadAllLines(sFile); } 

使用DelayedFileSystemWatcher.cs类http://blogs.msdn.com/b/ahamza/archive/2006/02/06/526222.aspx

然后是这段代码。 检查PrintFileSystemEventHandler事件处理程序。 它尝试在文件流中读取文件,如果有任何错误,则假定文件仍在读取,因此它等待一段时间(本例中为2秒),然后再次尝试。 检查CONVERSION:标签

 static void Main(string[] args) { DelayedFileSystemWatcher dfw = new DelayedFileSystemWatcher(@"C:\\Test", "*.*"); dfw.Changed += new FileSystemEventHandler(Program.FileSystemEventHandlerMethod); dfw.Created += new FileSystemEventHandler(Program.FileSystemEventHandlerMethod); dfw.Deleted += new FileSystemEventHandler(Program.FileSystemEventHandlerMethod); dfw.Error += new ErrorEventHandler(Program.ErrorEventHandlerMethod); dfw.Renamed += new RenamedEventHandler(Program.RenamedEventHandlerMethod); dfw.IncludeSubdirectories = true; dfw.ConsolidationInterval = 1000; dfw.EnableRaisingEvents = true; Console.WriteLine("Press \'q\' to quit the sample."); while (Console.Read() != 'q') ; //System.Threading.Thread.Sleep(60000); dfw.Dispose(); } private static void FileSystemEventHandlerMethod(object sender, FileSystemEventArgs e) { PrintFileSystemEventHandler(e); System.Console.WriteLine(); } private static void ErrorEventHandlerMethod(object sender, ErrorEventArgs e) { System.Console.WriteLine(e.GetException().Message); System.Console.WriteLine(); } private static void RenamedEventHandlerMethod(object sender, RenamedEventArgs e) { PrintRenamedEventHandler(e); System.Console.WriteLine(); } private static void PrintFileSystemEventHandler(FileSystemEventArgs e) { CONVERSION: try { if (e.ChangeType != WatcherChangeTypes.Deleted) { if (!isFolder(e.FullPath) && isFile(e.FullPath)) { FileStream fs = new FileStream(e.FullPath, FileMode.Open, FileAccess.Read, FileShare.None); fs.Close(); } } System.Console.WriteLine(e.Name + " " + e.FullPath + " " + e.ChangeType); } catch (System.IO.IOException) { Console.WriteLine("There was an IOException error or File is still copying. Retrying in 2 seconds..."); System.Threading.Thread.Sleep(2000); goto CONVERSION; } //System.Console.WriteLine(e.Name); //System.Console.WriteLine(e.FullPath); //System.Console.WriteLine(e.ChangeType); } private static bool isFolder(string strPath) { bool isFolderExist = false; try { isFolderExist = Directory.Exists(strPath); } catch { isFolderExist = false; } return isFolderExist; } private static bool isFile(string strPath) { bool isFileExist = false; try { isFileExist = File.Exists(strPath); } catch { isFileExist = false; } return isFileExist; } private static void PrintRenamedEventHandler(RenamedEventArgs e) { PrintFileSystemEventHandler(e); System.Console.WriteLine(e.OldName); System.Console.WriteLine(e.OldFullPath); } 

我没有项目的链接。 但这将有所帮助。

我支持Shay Erlichmen接受的解决方案。 但是,a)你可能不想用访问模式FileAccess.Read打开文件,把它作为一个只读文件

b)一些程序在下载时,文件将有一些有趣的扩展,完成后,扩展名将会改变,虽然文件已经完成,但你将找不到文件exception。

因此处理exception,并订阅file.renamed事件

完成复制后,您不会收到AFAIK通知,您可以实施重试机制。
如果您遇到剪切违规,只需触发计时器即可在X秒内重试该操作。
第二次重试应该在X * 2秒之后,依此类推(当然有一些限制)。

只需在你的fswCreated ,如果可能的话,使用Thread.Sleep(500)睡眠约1/2秒。 这应该给你计算机完成文件编写所需的时间。

当然,对于较慢的硬盘驱动器,这可能或可能有足够的时间。