【C# IO 操作】 文件系统侦听 FileSystemWatcher
阅读原文时间:2023年07月12日阅读:2

侦听器 :
FileSystemWatcher

  1. FileSystemWatcher常用属性有:
  • Filter :获取或设置用于确定目录中要监视哪些文件的过滤器字符串。Filter 属性设置为空字符串 ("") 或使用通配符(“*.*”)。若要监视特定的文件,请将 Filter 属性设置为该文件名。例如,若要监视文件 MyDoc.txt 中的更改,请将 Filter 属性设置为“MyDoc.txt”。也可以监视特定类型文件中的更改。例如,若要监视文本文件中的更改,请将 Filter 属性设置为“*.txt”。

  • IncludeSubdirectories:获取或设置是否监控被监控目录的子目录。

  • InternalBufferSize:内部缓冲区大小,最大为64K(侦听网络时候用),默认为8K。
    InternalBufferSize消息池是存放通知程序文件的修改信息,如果同一时刻有很多的文件被修改是可能溢出,FileSystemWatcher并不保证捕获所有的修改,InternalBufferSize消息池,如果溢出则会造成事件丢失,可以设置这个值,fsWather.InternalBufferSize
    = XXXXXX(默认值为 8192
    (8K)。);项目中只是监视某个文件夹中修改时间最新的文件,始终只是一个TXT文件,所以没有修改默认值,已经很够用了,具体多块的同时修改多少个文件会超出默认的8192,这边内存使用的是非分页缓冲内存(Non paged memory pool)点开任务管理器的性能一栏,可以看到下面的非分页缓冲池(Non paged memory pool)达到了1个G,这说明某个驱动发生了内存泄露

    (memory leak)。治标的解决办法只有关机重启。治本的解决方法是更新所有驱动。

    如果你不愿意更新所有的驱动,那么就要下载一款名为poolmoon的软件,分析是哪个东西造成的高非分页内存占用,然后更新一下就行了。

  • path:需要监控的文件夹路径

  • EnableRaisingEvents :设置是否开始监控。(默认为fals

  • NotifyFilter :设置文件的哪些属性的变动会触发Changed事件,可设置的类型如下:

  • Attributes           --  文件或文件夹的属性。  
                 CreationTime   --  文件或文件夹的创建时间。  
                 DirectoryName --  目录名。(常用) //用来侦听名字变更的,配合rename事件使用
                 FileName          --  文件名。 (常用)//用来侦听名字变更的,配合rename事件使用
                 LastAccess       --  文件或文件夹上一次打开的日期。  
                 LastWrite           --  上一次向文件或文件夹写入内容的日期。  //杀毒软件会修改LastWrite,会触发changge
                 Security              --  文件或文件夹的安全设置。  
                 Size                    --   文件或文件夹的大小。 (常用)

使用 FileSystemWatcher 类时,请注意以下事项。

1) 对包括隐藏文件(夹)在内的所有文件(夹)进行监控。

2) 您可以为 InternalBufferSize 属性(用于监视网络上的目录)设置的最大大小为 64 KB。

枚举:
WatcherChangeTypes

子项:All                 -- 文件或文件夹的创建、删除、更改或重命名。  
                       Changed     -- 文件或文件夹的更改。更改的类型包括大小、属性、安全设置、最近写入时间和最近访问时间方面的更改。  
                       Created       -- 文件或文件夹的创建。  
                       Deleted       --  文件或文件夹的删除。  
                       Renamed   --  文件或文件夹的重命名。 

事件参数:
FileSystemEventArgs
ErrorEventArgs

RenamedEventArgs

FileSystemEventArgs 对象:

成员: Name:     获取受影响的文件或目录的名称。 注意:如果是级联监控子目录的话,该值为从监控目录的下个目录到受影响的文件的路径,而不只是受影响的文件名。

FullPath : 获取受影响的文件或目录的完全限定的路径。

ChangeType :获取受影响的文件或目录的发生的事件类型。

RenamedEventArgs 对象:

成员: Name:           获取受影响的文件或目录的新名称。

OldName :    获取受影响的文件或目录的旧名称。

FullPath :      获取受影响的文件或目录的完全限定的路径。

OldFullPath : 获取受影响的文件或目录的前一个完全限定的路径。

ChangeType :获取受影响的文件或目录的发生的事件类型。

事件委托:
FileSystemEventHandler

ErrorEventHandler

RenamedEventHandler

FileSystemWatcher使用时候遇到的问题:

1、C#中FileSystemWatcher类的Changed事件触发多次的问题,解决方案如下:

void OnChange(object sender, FileSystemEventArgs e)
{
bool let = false;
if (let )
{
Console.WriteLine($"{e.Name} changing");
let = true;
}
else
{
let = false;

}  

}

2、杀毒软件会修改lasswrite 从而触发 change事件。解决方案如下:

不添加 NotifyFilter.lasswrite枚举

filters = NotifyFilters.Attributes
                                 | NotifyFilters.CreationTime
                                 | NotifyFilters.DirectoryName  //这个是rename事件 用的
                                 | NotifyFilters.FileName   //这个是rename事件 用的
                                 | NotifyFilters.LastAccess
                                 | NotifyFilters.Security
                                 | NotifyFilters.Size;*/

class FileSystemWatcherTest
{

static void Main()  
{  
    #region  新建文件夹和文件  
    //把桌面设置为当前目录  
    Directory.SetCurrentDirectory(Environment.GetFolderPath(Environment.SpecialFolder.Desktop));

    //在当前目录新建文件夹  
    DirectoryInfo directoryInfo = new DirectoryInfo("WatcherTest");  
    directoryInfo.Create();

    //显示当前目录  
    Console.WriteLine(Environment.CurrentDirectory);

    //在WatcherTest 目录新建文件  
    FileInfo fileInfo = new FileInfo(Path.Combine(directoryInfo.Name, "readme.txt"));  
    var filestream= fileInfo.Create();    

    //关闭文件流  
    filestream.Close(); 

    //创建子文件夹  
    DirectoryInfo subinfo = directoryInfo.CreateSubdirectory("sub");  
    subinfo.Create();

    //在子文件夹sub下创建 文件sub2.txt  
    FileInfo subinfo2 = new FileInfo(Path.Combine(subinfo.FullName, "sub2.txt"));  
    FileStream subfs = subinfo2.Create();  
    subfs.Close();// 在删除文件之前必须删除FileSteam  
    #endregion

    #region 监听刚刚新建的文件夹和文件 变更情况  
 using var   watcher = new FileSystemWatcher(directoryInfo.FullName);

    watcher.Filter = "\*.txt";  
    watcher.NotifyFilter = NotifyFilters.Security |  
                    NotifyFilters.Attributes |  
                    NotifyFilters.CreationTime |  
                    NotifyFilters.LastAccess |  
                    NotifyFilters.LastWrite |  
                    NotifyFilters.LastAccess |  
                    NotifyFilters.FileName |  
                    NotifyFilters.DirectoryName |  
                    NotifyFilters.Size;

    /\*        watcher.NotifyFilter = NotifyFilters.Attributes  
                                     | NotifyFilters.CreationTime  
                                     | NotifyFilters.DirectoryName  
                                     | NotifyFilters.FileName  
                                     | NotifyFilters.LastAccess  
                                     | NotifyFilters.LastWrite  
                                     | NotifyFilters.Security  
                                     | NotifyFilters.Size;\*/

    watcher.Changed +=  Changed;  
    watcher.Created += Created;  
    watcher.Renamed += Renamed;  
    watcher.Deleted += Deleted;  
    watcher.Error += Error;

    //是否侦听子目录  
    watcher.IncludeSubdirectories = true;   

    //允许触发侦听事件  
    watcher.EnableRaisingEvents = true;

    while (Console.Read()!='q') ;

    watcher.Dispose();

    #endregion

}

private static void Error(object sender, ErrorEventArgs e)  
{  
    Console.WriteLine($"Error:{0}", e.ToString());  
}

private static void Deleted(object sender, FileSystemEventArgs e)  
{  
    Console.WriteLine($"{e.Name} is Deleted");  
}

private static void Renamed(object sender, RenamedEventArgs e)  
{  
    Console.WriteLine($"{e.OldName} Renamed :{e.Name}");  
}

private static void Created(object sender, FileSystemEventArgs e)  
{  
    Console.WriteLine($"{e.Name} Created :{e.FullPath}");  
}

private static void Changed(object sender, FileSystemEventArgs e)  
{  
    if(e.ChangeType == WatcherChangeTypes.Changed)  
    Console.WriteLine($"{e.Name}Changed:{e.FullPath}");

}  

}

手机扫一扫

移动阅读更方便

阿里云服务器
腾讯云服务器
七牛云服务器

你可能感兴趣的文章