首页 > 代码库 > 如何实现文件和文件夹的监控功能

如何实现文件和文件夹的监控功能

分析问题

  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缓存溢出的情况。