翼度科技»论坛 编程开发 .net 查看内容

使用C#如何监控选定文件夹中文件的变动情况?

4

主题

4

帖子

12

积分

新手上路

Rank: 1

积分
12
目录✨

1、前言
2、效果
3、具体实现
​      页面设计
​      全部代码
​      FileSystemWatcher的介绍
​                 FileSystemWatcher的构造函数
​                 FileSystemWatcher的属性
​                 FileSystemWatcher的事件
4、总结
前言✨

有时候我们会有监控电脑上某一个文件夹中文件变动情况的需求,在本文中,我也会以一个具体的例子,说明在C#中如何使用FileSystemWatcher类来实现上述需求。
效果✨



具体实现✨

如果你对C#如何监控选定文件夹中文件的变动情况感兴趣,可以继续往下阅读。
界面设计

为了更好的演示效果,我这里winform的界面设计如下:

很简单,只有一个button与一个richtextbox,button用来指定被监控的文件,richtextbox用来输出一些信息。
全部代码
  1. namespace FileSystemWatcherDemo
  2. {
  3.     public partial class Form1 : Form
  4.     {
  5.         public Form1()
  6.         {
  7.             InitializeComponent();
  8.         }
  9.         private void button1_Click(object sender, EventArgs e)
  10.         {
  11.             // 创建一个 FolderBrowserDialog 实例
  12.             FolderBrowserDialog folderBrowserDialog = new FolderBrowserDialog();
  13.             // 设置对话框的标题
  14.             folderBrowserDialog.Description = "选择文件夹";
  15.             // 如果用户点击了“确定”按钮
  16.             if (folderBrowserDialog.ShowDialog() == DialogResult.OK)
  17.             {
  18.                 richTextBox1.Text = "";
  19.                 // 获取用户选择的文件夹路径
  20.                 string selectedFolder = folderBrowserDialog.SelectedPath;
  21.                 // 提示被监控文件夹路径
  22.                 richTextBox1.Text += $"被监控的文件夹为:{selectedFolder}\r\n";
  23.                 var watcher = new FileSystemWatcher($"{selectedFolder}");
  24.                
  25.                 watcher.NotifyFilter = NotifyFilters.Attributes
  26.                                 | NotifyFilters.CreationTime
  27.                                 | NotifyFilters.DirectoryName
  28.                                 | NotifyFilters.FileName
  29.                                 | NotifyFilters.LastAccess
  30.                                 | NotifyFilters.LastWrite
  31.                                 | NotifyFilters.Security
  32.                                 | NotifyFilters.Size;
  33.                 watcher.Changed += OnChanged;
  34.                 watcher.Created += OnCreated;
  35.                 watcher.Deleted += OnDeleted;
  36.                 watcher.Renamed += OnRenamed;
  37.                
  38.                 watcher.Filter = "*.txt";
  39.                 watcher.IncludeSubdirectories = true;
  40.                 watcher.EnableRaisingEvents = true;
  41.             }
  42.             else
  43.             {
  44.                 MessageBox.Show("您本次没有选择文件夹!!!");
  45.             }
  46.          
  47.            
  48.    
  49.         }
  50.         private void AppendMessageToRichTextBox(string message)
  51.         {
  52.             // 在RichTextBox中添加提示信息        
  53.             richTextBox1.Invoke(new Action(() =>
  54.             {
  55.                 richTextBox1.AppendText(message + Environment.NewLine);
  56.             }));
  57.         }
  58.         private void OnChanged(object sender, FileSystemEventArgs e)
  59.         {
  60.             if (e.ChangeType != WatcherChangeTypes.Changed)
  61.             {
  62.                 return;
  63.             }
  64.             AppendMessageToRichTextBox($"Changed: {e.FullPath}");
  65.         }
  66.         private void OnCreated(object sender, FileSystemEventArgs e)
  67.         {
  68.             string value = $"Created: {e.FullPath}";
  69.             AppendMessageToRichTextBox($"Created: {e.FullPath}");
  70.         }
  71.         private  void OnDeleted(object sender, FileSystemEventArgs e)
  72.         {
  73.             AppendMessageToRichTextBox($"Deleted: {e.FullPath}");
  74.         }
  75.         private  void OnRenamed(object sender, RenamedEventArgs e)
  76.         {      
  77.             AppendMessageToRichTextBox($"Renamed:");
  78.             AppendMessageToRichTextBox($"    Old: {e.OldFullPath}");
  79.             AppendMessageToRichTextBox($"    New: {e.FullPath} ");           
  80.         }
  81.      
  82.     }
  83. }
复制代码
FileSystemWatcher的介绍

看过以上代码,会发现核心就是FileSystemWatcher的使用。接下来我将介绍一下C#中的FileSystemWatcher类。
FileSystemWatcher是C#中的一个类,该类可以侦听文件系统更改通知,并在目录或目录中的文件发生更改时引发事件。
FileSystemWatcher的构造函数

该类有三种构造函数,如下所示:
形式含义FileSystemWatcher()初始化 FileSystemWatcher 类的新实例。FileSystemWatcher(String)初始化 FileSystemWatcher 类的新实例,给定要监视的目录。FileSystemWatcher(String, String)初始化 FileSystemWatcher类的新实例,给定要监视的目录和文件类型。
  1. var watcher = new FileSystemWatcher($"{selectedFolder}");
复制代码
本文中我选择的就是第二种构造函数,指定要监视的目录。
FileSystemWatcher的属性

现在介绍一下在本示例中用到的FileSystemWatcher的属性,如下所示:
名称类型含义EnableRaisingEventsbool设置FileSystemWatcher是否有效Filterstring设置一个要监控的文件的格式FiltersCollection设置多个要监控的文件的格式IncludeSubdirectoriesbool获取或设置一个值,该值指示是否应监视指定路径中的子目录NotifyFilterNotifyFilters获取或设置要监视的更改的类型Pathstring获取或设置要监视的目录的路径现在来解释下所用到的代码的含义:
  1. watcher.Filter = "*.txt";
复制代码
表示要监控的文件为.txt格式。
  1. watcher.IncludeSubdirectories = true;
复制代码
表示指定路径中的子目录也要监视。
  1. watcher.EnableRaisingEvents = true;
复制代码
表示该对象可以触发事件,也就是还有效。
  1. watcher.NotifyFilter = NotifyFilters.Attributes
  2.                                 | NotifyFilters.CreationTime
  3.                                 | NotifyFilters.DirectoryName
  4.                                 | NotifyFilters.FileName
  5.                                 | NotifyFilters.LastAccess
  6.                                 | NotifyFilters.LastWrite
  7.                                 | NotifyFilters.Security
  8.                                 | NotifyFilters.Size;
复制代码
设置要监视的更改的类型。NotifyFilter属性的类型为NotifyFilters枚举类型。
NotifyFilters枚举类型:
  1. [System.Flags]
  2. public enum NotifyFilters
复制代码
指定要在文件或文件夹中监视的更改。
此枚举支持其成员值的按位组合。
该枚举类型包含的值与含义如下所示:
名称含义Attributes文件或文件夹的属性CreationTime文件或文件夹的创建时间DirectoryName目录名FileName文件的名称LastAccess文件或文件夹上一次打开的日期LastWrite上一次向文件或文件夹写入内容的日期Security文件或文件夹的安全设置Size文件或文件夹的大小在这里使用了该枚举类型的按位组合表示这几种更改的类型要受到监视。
FileSystemWatcher的事件

FileSystemWatcher中的事件如下:
名称含义Changed当更改指定 Path 中的文件和目录时发生Created当在指定Path 中创建文件和目录时发生Deleted删除指定Path中的文件或目录时发生Renamed重命名指定 Path中的文件或目录时发生Error当 FileSystemWatcher 的实例无法继续监视更改或内部缓冲区溢出时发生
  1.                 watcher.Changed += OnChanged;
  2.                 watcher.Created += OnCreated;
  3.                 watcher.Deleted += OnDeleted;
  4.                 watcher.Renamed += OnRenamed;
复制代码
在这里我使用到了Changed、Created、Deleted和Renamed事件。
我将以Changed  事件为例,详细解释一下:
  1. watcher.Changed += OnChanged;
复制代码
这行代码的含义。
我们查看FileSystemWatcher的源代码,Changed事件的代码如下所示:
  1. /// <devdoc>
  2. ///    Occurs when a file or directory in the specified <see cref='System.IO.FileSystemWatcher.Path'/> is changed.
  3. /// </devdoc>
  4. public event FileSystemEventHandler? Changed
  5. {
  6.     add
  7.     {
  8.         _onChangedHandler += value;
  9.     }
  10.     remove
  11.     {
  12.         _onChangedHandler -= value;
  13.     }
  14. }
复制代码
可知将值赋给了_onChangedHandler,我们再来查看_onChangedHandler的定义:
  1. // Event handlers
  2. private FileSystemEventHandler? _onChangedHandler;
复制代码
类型为FileSystemEventHandler?与Changed事件一致,再来看看FileSystemEventHandler?的定义:
  1. public delegate void FileSystemEventHandler(object sender, FileSystemEventArgs e);
复制代码
发现是一个参数类型分别为object、FileSystemEventArgs返回值类型为空的委托类型。
object我们知道,那么FileSystemEventArgs又是什么呢?
查看它的源码,截取一部分,如下所示:
  1. public class FileSystemEventArgs : EventArgs
  2. {
  3.      private readonly WatcherChangeTypes _changeType;
  4.      private readonly string? _name;
  5.      private readonly string _fullPath;
  6.      /// <devdoc>
  7. ///    Gets one of the <see cref='System.IO.WatcherChangeTypes'/> values.
  8. /// </devdoc>
  9. public WatcherChangeTypes ChangeType
  10. {
  11.     get
  12.     {
  13.         return _changeType;
  14.     }
  15. }
  16. /// <devdoc>
  17. ///    Gets the fully qualified path of the affected file or directory.
  18. /// </devdoc>
  19. public string FullPath
  20. {
  21.     get
  22.     {
  23.         return _fullPath;
  24.     }
  25. }
  26. /// <devdoc>
  27. ///       Gets the name of the affected file or directory.
  28. /// </devdoc>
  29. public string? Name
  30. {
  31.     get
  32.     {
  33.         return _name;
  34.     }
  35. }
  36. }
复制代码
发现FileSystemEventArgs继承自EventArgs,而EventArgs表示包含事件数据的类的基类,因此可以明白FileSystemEventArgs表示为目录事件:Changed, Created, Deleted提供数据的类。
FileSystemEventArgs提供三个数据分别为ChangeType、FullPath、Name。
那ChangeType是什么呢?
查看ChangeType的定义:
  1. //
  2. // 摘要:
  3. //     Changes that might occur to a file or directory.
  4. [Flags]
  5. public enum WatcherChangeTypes
  6. {
  7.      //
  8.      // 摘要:
  9.      //     The creation of a file or folder.
  10.      Created = 1,
  11.      //
  12.      // 摘要:
  13.      //     The deletion of a file or folder.
  14.      Deleted = 2,
  15.      //
  16.      // 摘要:
  17.      //     The change of a file or folder. The types of changes include: changes to size,
  18.      //     attributes, security settings, last write, and last access time.
  19.      Changed = 4,
  20.      //
  21.      // 摘要:
  22.      //     The renaming of a file or folder.
  23.      Renamed = 8,
  24.      //
  25.      // 摘要:
  26.      //     The creation, deletion, change, or renaming of a file or folder.
  27.      All = 15
  28. }
复制代码
是一个枚举类型,表示更改的类型。
现在回过头来看:
  1. watcher.Changed += OnChanged;
复制代码
OnChanged方法如下:
  1.   private void OnChanged(object sender, FileSystemEventArgs e)
  2.   {
  3.       if (e.ChangeType != WatcherChangeTypes.Changed)
  4.       {
  5.           return;
  6.       }
  7.       AppendMessageToRichTextBox($"Changed: {e.FullPath}");
  8.   }
复制代码
为什么可以将OnChanged方法订阅到watcher.Changed事件上呢?
因为OnChanged方法与watcher.Changed事件中的委托类型FileSystemEventHandler的返回类型和签名是相同的。
OnChanged方法的返回类型与签名如下:
  1. private void OnChanged(object sender, FileSystemEventArgs e)
复制代码
FileSystemEventHandler委托类型的定义如下:
  1. public delegate void FileSystemEventHandler(object sender, FileSystemEventArgs e);
复制代码
现在已经理解了订阅事件,那么什么时候触发事件呢?
查看FileSystemWatcher的部分源码:
  1. /// <devdoc>
  2. ///    Raises the <see cref='System.IO.FileSystemWatcher.Changed'/> event.
  3. /// </devdoc>
  4. protected void OnChanged(FileSystemEventArgs e)
  5. {
  6.      InvokeOn(e, _onChangedHandler);
  7. }
  8. private void InvokeOn(FileSystemEventArgs e, FileSystemEventHandler? handler)
  9. {
  10.      if (handler != null)
  11.      {
  12.          ISynchronizeInvoke? syncObj = SynchronizingObject;
  13.          if (syncObj != null && syncObj.InvokeRequired)
  14.              syncObj.BeginInvoke(handler, new object[] { this, e });
  15.          else
  16.              handler(this, e);
  17.      }
  18. }
复制代码
当发生相应的改变时,就会调用FileSystemWatcher类的OnChanged方法,从而触发事件。
总结✨

本文通过一个实例,介绍了如何通过C#中的FileSystemWatcher类实现监控选定的文件夹,希望对你有所帮助。

来源:https://www.cnblogs.com/mingupupu/Undeclared/17933098.html
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x

举报 回复 使用道具