分析问题
FileSystemWatcher类型定义在System.IO命名空间下,它的功能是监控某个文件夹下特定文件系统的变化。这样的变化可以包括创建、文件修改、重命名、删除等。程序员可以通过设置一个NotifyFilters枚举类型的成员来订阅感兴趣的信息。下表列出了NotifyFilters的所有项及其代表的意义。
名称 | 说明 | 长度 |
Attributes | 文件或文件夹的属性 | 4 |
CreationTime | 文件或文件夹的创建时间 | 64 |
DirectoryName | 目录名 | 2 |
FileName | 文件名 | 1 |
LastAccess | 文件或文件夹上一次打开的日期 | 32 |
LastWrite | 上一次向文件或文件夹写入内容的日期 | 16 |
Security | 文件或文件夹的安全设置 | 256 |
Size | 文件或文件夹的大小 | 8 |
程序员通过设置感兴趣的文件夹和文件、变化的类型以及处理时间的方法,就能实现对文件系统的侦听。以下代码展示了FileSystemWatcher的使用方法。
说明
.NET中的事件机制将在本书后续章节中有所覆盖,简单来说,事件代表一个可以触发回调方法的特殊类型。
using System; using System.IO; namespace Test { class UseFileSystemWatcher { //退出程序命令 private const string Exit = "exit"; //监视的文件夹 private const string Folder = @"D:\Test"; private FileSystemWatcher _fsw; public UseFileSystemWatcher() { _fsw = new FileSystemWatcher(); //建立监测文件夹 if (Directory.Exists(Folder)) { Directory.Delete(Folder, true); } Directory.CreateDirectory(Folder); _fsw.Path = Folder; //这里选择最后访问文件时间、最后写文件时间、文件名、 //文件夹名变化时,触发事件 _fsw.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite | NotifyFilters.FileName | NotifyFilters.DirectoryName; //这里选择监测所有的zip文件 _fsw.Filter = "*.rar"; //为这些事件添加处理方法。 _fsw.Changed+=new FileSystemEventHandler(OnChanged); _fsw.Created+=new FileSystemEventHandler(OnChanged); _fsw.Deleted+=new FileSystemEventHandler(OnChanged); _fsw.Renamed += new RenamedEventHandler(OnRenamed); //这里开始所有事件会被触发 _fsw.EnableRaisingEvents = true; } //处理变化事件,变化可以包含创建、修改和删除 private void OnChanged(object source, FileSystemEventArgs e) { Console.WriteLine("文件:{0}{1}", e.FullPath, e.ChangeType.ToString()); } //处理重命名事件 private static void OnRenamed(object source, RenamedEventArgs e) { Console.WriteLine("文件:{0}重命名为:{1}",e.OldFullPath,e.FullPath); } static void Main() { try { UseFileSystemWatcher ws = new UseFileSystemWatcher(); while (Console.ReadLine()!=Exit) { } } finally { //清理测试数据 if (Directory.Exists(Folder)) { Directory.Delete(Folder, true); } } } } }
以上代码创建了一个监测D:\Test目录的FileSystemWatcher对象,并且订阅了感兴趣的修改、创建、删除等事件。在程序运行过程中,读者可以尝试在D:\Test目录下创建、删除、复制文件,控制台会输出相应的信息,最后使用者可以输入exit来结束这段程序的运行。
关于FileSystemWatcher产生的最多疑问可能就是文件复制时Changed事件为何被多次触发。这并不是.NET的Bug,而是正常文件系统操作中确实包含了多个简单操作。例如一个移动操作,可能涉及多次修改文件的操作,并且可能产生文件的创建和删除动作。
注意
某些特殊的监控软件,例如防火墙软件等,都可能会导致FileSystemWatcher监控事件的发生。
虽然FileSystemWatcher使用非常简单,但在设计使用FileSystemWatcher的系统时仍需要注意其某些细节。FileSystemWatcher会维护一个内部缓冲来接受文件系统的修改通知,但短时间内文件系统的修改数量过多时,缓冲就会溢出,这时候就会导致某些修改事件被丢失。程序员可以通过InternalBufferSize来修改内部缓存的大小。
技巧
笔者不建议读者随意加大FileSystemWatcher的内部缓存大小,因为这对性能的影响非常大。笔者建议读者使用其他机制来避免文件修改事件的丢失,比如加快处理速度、减少监控范围等。
答案
.NET提供了FileSystemWatcher类型来实现文件系统的监控。程序员通过设置监控目录、监控类型和回调方法,就可以方便地实现监控的功能。但需要小心FileSystemWatcher缓存溢出的情况。
如何实现文件和文件夹的监控功能