使用FileSystemWatcher监听文件状态
更新记录
本文迁移自Panda666原博客,原发布时间:2021年7月2日。
一、FileSystemWatcher类型介绍
在.NET中使用 FileSystemWatcher 类型可以进行监视指定目录的更改。通过自定义的监听设置,可监视指定目录中的文件或子目录的更改。通过该类可以不只是监视本地计算机的文件,还可以监听网络驱动器或远程计算机的文件。
FileSystemWatcher 类型所在命名空间
using System.IO;
注意:一定要确保新建/修改等完成后再进行对文件的操作,可以检测文件是否可用,再进行操作。
二、具体实例
using System;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
namespace PandaTestClass
{
class Program
{
///
/// 打开文件,用于测试文件是否可用
///
///
///
///
[DllImport("kernel32.dll")]
public static extern IntPtr _lopen(string lpPathName, int iReadWrite);
///
/// 关闭句柄
///
///
///
[DllImport("kernel32.dll")]
public static extern bool CloseHandle(IntPtr hObject);
///
/// 文件打开的模式,读写权限
///
public const int OF_READWRITE = 2;
///
/// 文件打开的模式,进程间共享读写
///
public const int OF_SHARE_DENY_NONE = 0x40;
///
/// 文件打开错误标志位
///
public static readonly IntPtr HFILE_ERROR = new IntPtr(-1);
static void Main(string[] args)
{
//新建文件监听器
FileSystemWatcher watcher = new FileSystemWatcher();
//====配置文件监听器=====
//监听的目录
string monitoredPath = @"F:/";
//监听的文件类型
string monitoredFileType = "*.txt|*.cs";
//监听的修改的具体操作类型
NotifyFilters notifyFilters = NotifyFilters.FileName
| NotifyFilters.Size
| NotifyFilters.LastWrite;
//设置参数
watcher.Path = monitoredPath;
monitoredFileType.Split("|")
.ToList()
.ForEach(elem => watcher.Filters.Add(elem));
watcher.NotifyFilter = notifyFilters;
//====配置文件监听器=====
//====绑定事件处理函数====
//(增)绑定文件创建处理函数
watcher.Created += (object sender, FileSystemEventArgs args) => {
Console.WriteLine("文件创建啦");
Console.WriteLine($"文件名:{args.Name}");
Console.WriteLine($"所在路径:{args.FullPath}");
};
//(删)绑定文件删除处理函数
watcher.Deleted += (object sender, FileSystemEventArgs args) => {
Console.WriteLine("文件删除啦");
Console.WriteLine($"文件名{args.Name}");
Console.WriteLine($"所在路径:{args.FullPath}");
};
//(改)绑定文件重命名处理函数
watcher.Renamed += (object sender, RenamedEventArgs args) => {
Console.WriteLine("文件重命名啦");
Console.WriteLine($"旧文件名{args.OldName}");
Console.WriteLine($"新文件名{args.Name}");
};
//(改)绑定文件修改事件处理函数
watcher.Changed += (object sender, FileSystemEventArgs args) => {
Console.WriteLine("文件修改啦");
Console.WriteLine($"被修改的文件是{args.Name}");
Console.WriteLine($"被修改的文件文件路径是{args.FullPath}");
Console.WriteLine($"修改的类型{args.ChangeType.ToString()}");
//====检测创建后是否可用(比如:是否复制完成)====
//先检测文件是否存在
FileInfo fileInfo = new(args.FullPath);
if (!fileInfo.Exists)
{
return;
}
//检测文件是否复制完成
IntPtr vHandle = _lopen(args.FullPath, OF_READWRITE | OF_SHARE_DENY_NONE);
if (vHandle == HFILE_ERROR)
{
Console.WriteLine("文件还未复制完成");
return;
}
//释放句柄
CloseHandle(vHandle);
//可以对文件进行操作
Console.WriteLine("可以对文件进行操作了");
//====检测创建后是否可用(比如:是否复制完成)====
//对文件具体操作的代码
};
//绑定文件错误事件处理函数
watcher.Error += (object sender, ErrorEventArgs args) =>{
Console.WriteLine("文件出错啦");
Console.WriteLine($"出错信息:{args.GetException().Message}");
};
//====绑定事件处理函数====
//开启监听
watcher.EnableRaisingEvents = true;
//等待用户关闭监听
while (true)
{
Console.WriteLine("如需关闭监听,请按Y:");
if((Console.ReadKey()).Key == ConsoleKey.Y)
{
//释放监听器
watcher.Dispose();
return;
}
}
}
}
}
说明:代码中基本每条语句都有注释,也没有过多的分支,一眼就可以看明白,我也就不需要过的的解释了。但需要注意的是代码中添加了处理检测文件是否可用的代码,这些代码用到了互操作代码,如果您不需要检测文件是否可用,可以将其删除。代码为了观看方法把所有代码都写在一个方法中,如果您要用在项目中,记得遵守SOLID,将代码进行拆分成多个单独的部分。