一个更好的文件监控类,基于 DotNet 官方提供的 FileSystemWatcher

简介: 一个更好的文件监控类,基于 DotNet 官方提供的 FileSystemWatcher

缘起

前一段时间,想使用 .net 监听特定文件夹中的文件是否发生变化。网上一搜,可以使用 .net 官方提供的 FileSystemWatcher,很开心的写好了代码。随着使用的不断深入,发现了 FileSystemWatcher 几个不够完善的地方。比如,

  1. 事件触发时,文件可能还不能被访问。
  2. 如果监听选项设置的过多,则有可能会触发多次文件变化事件。
  3. 监听过滤器不够灵活,我没找到同时监听多种特定文件类型的方法。比如,同时只监听 .docx.bmp 文件。

鉴于此,基于 .net 官方提供的 FileSystemWatcher,我又封装了一个新的类。可以在一定程度上解决以上几个问题。

问题及解决方案

  1. 当事件触发的时候,文件还不能被访问。如何重现?

    重现方法:

    通过共享文件夹拷贝一个大文件,基本上可以重现。

    解决方案:

    在调用用户的回调函数前,先判断文件是否可以访问。

    实现代码:

    WaitForFileReadyToAccess 可以用来开启/关闭此功能。

    WaitUntilCanAccess() 不断尝试访问文件,以此来确定是否可以访问该文件。

    用户可以通过 FileAccessCheckIntervalMs 来设置尝试间隔,单位是毫秒。

    用户可以通过 MaxWaitMs 设置最大等待时间,单位是毫秒。

  1. 相同的事件触发多次。如何重现?

    重现方法:

    NotifyFilters 设置成下面的样子,拷贝一张文件到监听路径下即可重现。

    NotifyFilters _notifyFilters = NotifyFilters.DirectoryName | NotifyFilters.FileName
            | NotifyFilters.LastWrite | NotifyFilters.CreationTime | NotifyFilters.LastAccess
            | NotifyFilters.Attributes | NotifyFilters.Size | NotifyFilters.Security
            ;
    

    解决方案:

    在调用用户的回调函数前,稍微等一段时间,合并这段时间内的相同事件。

    实现代码:

    TryMergeSameEvent 用来开启/关闭事件合并功能。

    如果 TryMergeSameEvent 为真,那么会通过 eventDataList = eventDataList.Distinct().ToList(); 来去重。

    用户可以通过 DelayTriggerMs 指定延时触发间隔,单位是毫秒。只有在合并事件开启的时候才生效。

  1. 不能同时监听多种特定类型。

    重现方法:

    我没能找到同时监听多种特定类型的方法。

    解决方案:

    封装一个新类。用户可以通过 | 分割多个过滤条件。根据每个过滤条件构造对应的由系统提供的 FileSystemWatcher,保存到

    List<FileSystemWatcher> 中。

    实现代码:

    char[] splitter = {
          '|' };
    var filterList = Filters.Split(splitter).ToList();
    foreach (var filter in filterList)
    {
         
      FileSystemWatcher watcher = new FileSystemWatcher();
    
      watcher.Filter = filter;
      watcher.Path = this.Path;
      watcher.IncludeSubdirectories = this.Recursive;
      watcher.NotifyFilter = this.NotifyFilters;
      watcher.Created += this.OnFileSystemEventHandler;
      watcher.Deleted += this.OnFileSystemEventHandler;
      watcher.Changed += this.OnFileSystemEventHandler;
      watcher.Renamed += this.OnRenamedEventHandler;
      watcher.Error += this.OnErrorHandler;
      watcher.EnableRaisingEvents = true;
      WatcherList.Add(watcher);
    }
    

使用示例

public void OnFileChanged(object sender, System.IO.FileSystemEventArgs e)
{
   
  if (e.ChangeType == System.IO.WatcherChangeTypes.Created 
      || e.ChangeType == System.IO.WatcherChangeTypes.Changed)
  {
   
    this.Invoke(new MethodInvoker(delegate()
    {
   
      try
      {
   
        using (var imageStream = new FileStream(e.FullPath, FileMode.Open))
        {
   
          this.pictureBox1.Image = (Bitmap)Image.FromStream(imageStream);
        }
      }
      catch (Exception ex)
      {
   
        System.Diagnostics.Debug.WriteLine(string.Format("!!!! {0}", ex.ToString()));
      }
    }));
  }
}

private void Form1_Load(object sender, EventArgs e)
{
   
  var monitorPath = System.AppDomain.CurrentDomain.BaseDirectory;
  var fileWatcherEx = new FileSystemWatcherEx(monitorPath, "*.bmp|*.png|*.jpg|*.gif", true, "", OnFileChanged, OnFileChanged, OnFileChanged);
  fileWatcherEx.Start();
}

下载地址

我已经把这个简单的类开源了。欢迎感兴趣的小伙伴儿 clone star pr

githubhttps://github.com/BianChengNan/FileSystemWatcherEx

giteehttps://gitee.com/bianchengnan/FileSystemWatcherEx

如果不想克隆源码,也可以直接下载压缩包:

百度云:https://pan.baidu.com/s/1OBSFpQYRDQHhO5A0Yviqmw 提取码: yic3

CSDN:https://download.csdn.net/download/xiaoyanilw/19648448

总结

犹记得,2013 年在做网盘的时候(用的语言是 C++),也有监听文件变化的需求,我们使用的是 win32 api ReadDirectoryChanges 来实现的。相比原生 api.net 中的 FileSystemWatcher 确实方便了很多。但还有一些不方便的地方。如果你也有类似需求,可以试试 FileSystemWatcherEx

相关文章
|
存储 SQL Cloud Native
深入了解云原生数据库CockroachDB的概念与实践
作为一种全球领先的分布式SQL数据库,CockroachDB以其高可用性、强一致性和灵活性等特点备受关注。本文将深入探讨CockroachDB的概念、设计思想以及实践应用,并结合实例演示其在云原生环境下的优越表现。
|
10月前
|
Unix Linux 虚拟化
VMware Workstation 17.6.2 发布下载,现在完全免费无论个人还是商业用途
VMware Workstation 17.6.2 发布下载,现在完全免费无论个人还是商业用途
44831 16
VMware Workstation 17.6.2 发布下载,现在完全免费无论个人还是商业用途
|
NoSQL Java MongoDB
SpringBoot中MongoDB的那些骚操作用法
MongoDB作为一种NoSQL数据库,在不需要传统SQL数据库的表格结构的情况下,提供了灵活的数据存储方案。在Spring Boot中可以通过官方SDK、Spring JPA或MongoTemplate等方式集成MongoDB。文章重点介绍了Spring Data MongoDB提供的注解功能,例如`@Id`、`@Document`和`@Field`等,这些注解简化了Java对象到MongoDB文档的映射。此外,文中还讨论了MongoTemplate监听器的使用,包括设置主键值和日志记录等高级特性。
482 0
SpringBoot中MongoDB的那些骚操作用法
|
存储 分布式计算 监控
Spark中广播变量
【8月更文挑战第13天】
466 0
|
人工智能 文字识别 语音技术
学习资料大全​ | 一起来魔搭社区学AI吧!
魔搭社区特别推出研习社栏目,包含AI前沿技术解读、模型应用最佳实践、动手做AI应用(AIGC/Agent/RAG)等主题,持续更新,代码实战点击即运行
|
机器学习/深度学习 数据采集 人工智能
「AIGC」Stable Diffusion教程详解
**Stable Diffusion教程摘要:** Stable Diffusion是AI绘画工具,利用GAN学习艺术家风格。基础教程涵盖软件介绍、配置需求(NVIDIA GPU、Windows 10/11)、安装及基础操作,如模型切换、VAE使用、采样步数调整等。AI作画原理涉及U-net、Diffusion模型、文本映射(如CLIP)和条件生成。Stable Diffusion运用Latent Diffusion Model从潜在空间生成高清图像,开源且在艺术创作中广泛应用。
497 0
|
敏捷开发 测试技术 持续交付
极限编程(XP)原理与技巧:深入解析与实践
【5月更文挑战第8天】极限编程(XP)是一种敏捷开发方法,注重快速反馈、迭代开发和简单设计,以提高软件质量和项目灵活性。关键原则包括客户合作、集体代码所有权、持续集成等。实践中,使用故事卡片描述需求,遵循编程约定,实行TDD,持续重构,结对编程,并定期举行迭代会议。通过理解和应用XP,团队能提升效率,应对变化。
|
Web App开发 缓存 iOS开发
强制退出Mac程序的六种方法
强制退出Mac程序的六种方法
678 2
|
消息中间件 存储 Java
Kafka kafka在windows下的安装与配置
Kafka kafka在windows下的安装与配置
560 0
|
网络安全
LabVIEW崩溃后如何排查故障
LabVIEW崩溃后如何排查故障
230 0