public class DataFileSystemWatcher
{
/// <summary>
/// 程序启动
/// </summary>
public void StartProcess()
{
try
{
//启用监听,监听文件夹
Run();
}
catch (Exception ex)
{
Log.WriteLog(LogFile.Error, "检查ECA文件夹时出错\r\n" + ex);
}
}
/// <summary>
/// 监听事件
/// </summary>
public static void Run()
{
FileSystemWatcher watcher = new FileSystemWatcher();
//watcher.Path = AppDomain.CurrentDomain.BaseDirectory;
watcher.Path = @"E:\Share\ecn汇总\ECA\";//监听路径
/* 设置为监视 LastWrite 和 LastAccess 时间方面的更改,以及目录中文本文件的创建、删除或重命名。 */
watcher.NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.CreationTime
| NotifyFilters.FileName | NotifyFilters.DirectoryName;//NotifyFilters.LastAccess |
// 只监控.xls文件
watcher.Filter = "*.xls";
// 添加事件处理器。
watcher.Changed += new FileSystemEventHandler(OnChanged);
watcher.Created += new FileSystemEventHandler(OnChanged);
watcher.Deleted += new FileSystemEventHandler(OnChanged);
watcher.Renamed += new RenamedEventHandler(OnRenameed);
// 开始监控。
watcher.EnableRaisingEvents = true;
}
/// <summary>
/// 文件改变事件,增删改
/// </summary>
/// <param name="source"></param>
/// <param name="e"></param>
public static void OnChanged(object source, FileSystemEventArgs e)
{
try
{
//根据路径去顶那些文件发生修改
switch (e.ChangeType)
{
case WatcherChangeTypes.Created://新建文件
GetExcelData(e.FullPath, e.Name, 0, null);//具体处理逻辑
break;
case WatcherChangeTypes.Deleted://文件删除
GetExcelData(e.FullPath, e.Name, 2, null);//具体处理逻辑
break;
case WatcherChangeTypes.Changed://文件修改
GetExcelData(e.FullPath, e.Name, 1, null);//具体处理逻辑
break;
default:
break;
}
}
catch (Exception ex)
{
Log.WriteLog(LogFile.Error, "监听的OnChanged出错,出错类型" + e.ChangeType + "\r\n" + ex);
}
}
/// <summary>
/// 重命名事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private static void OnRenameed(object sender, RenamedEventArgs e)
{
try
{
//更新数据库
string md5_new = GetMD5HashFromFile(e.FullPath);//新MD5
//根据原来的路径和文件名,获取文件
ECAInfo info_dele = new BaseLink().SelectECAInfo(e.OldFullPath, e.OldName);
//更新数据
if (info_dele != null)
{
info_dele.ECAPath = e.FullPath;
info_dele.ECAName = e.Name;
new BaseLink().RenameECAInfo(info_dele,out string msg);//具体处理逻辑
Log.WriteLog(LogFile.Info, e.OldName + "重命名为->" + e.Name + msg);
}
}
catch (Exception ex)
{
Log.WriteLog(LogFile.Error, "文件发生重命名事件出错\r\n" + ex);
}
}
/// <summary>
/// 获取文件MD5值
/// </summary>
/// <param name="filePath"></param>
/// <returns></returns>
private static string GetMD5HashFromFile(string filePath)
{
try
{
FileStream file = new FileStream(filePath, FileMode.Open);
System.Security.Cryptography.MD5 md5 = new System.Security.Cryptography.MD5CryptoServiceProvider();
byte[] retVal = md5.ComputeHash(file);
file.Close();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < retVal.Length; i++)
{
sb.Append(retVal[i].ToString("x2"));
}
return sb.ToString();
}
catch (Exception ex)
{
Log.WriteLog(LogFile.Error, "获取文件MD5值出错\r\n" + ex);
return "";
}
}
}
}
参考博客:https://blog.csdn.net/chen_zw/article/details/7916262
上面只是之前找到的一种方案,后来找到一个更好的方法.可以执行多个监听,同时也弄清楚了一些问题,分享一下:先上代码:
FileSystemWatcher[] fswArr;
private delegate void setLogTextDelegate(FileSystemEventArgs e);
private delegate void renamedDelegate(RenamedEventArgs e);
/// <summary>
/// 开始按钮
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void start_tsbtn_Click(object sender, EventArgs e)
{
if (this.spcifiedFloder_rbtn.Checked)//指定文件
{
if (!string.IsNullOrEmpty(this.filePath_txt.Text))//文件路径
{
fswArr = new FileSystemWatcher[1];
fswArr[0] = new FileSystemWatcher();
fswArr[0].Path = this.filePath_txt.Text; //设置监控路径
fswArr[0].IncludeSubdirectories = this.subDirWatcher_chk.Checked; //获取或设置一个值,该值指示是否监视指定路径中的子目录。
fswArr[0].NotifyFilter = NotifyFilters.FileName | NotifyFilters.DirectoryName | NotifyFilters.Size;
fswArr[0].Created += new FileSystemEventHandler(this.fileSystemWatcher_EventHandle);
fswArr[0].Deleted += new FileSystemEventHandler(this.fileSystemWatcher_EventHandle);
fswArr[0].Changed += new FileSystemEventHandler(this.fileSystemWatcher_EventHandle);
fswArr[0].Renamed += new RenamedEventHandler(this.fileSystemWatcher_Renamed);
fswArr[0].EnableRaisingEvents = true;
}
else
{
MessageBox.Show("请先选择监控路径!");
return;
}
}
else
{
int checkedCount = this.dir_lvw.CheckedItems.Count;//选择的多个监听路径
if (checkedCount > 0)
{
fswArr = new FileSystemWatcher[checkedCount];
for (int i = 0; i < this.dir_lvw.CheckedItems.Count; i++)
{
fswArr[i] = new FileSystemWatcher();
fswArr[i].Path = this.dir_lvw.CheckedItems[i].Text;
fswArr[i].IncludeSubdirectories = this.subDirWatcher_chk.Checked; //获取或设置一个值,该值指示是否监视指定路径中的子目录。
fswArr[i].NotifyFilter = NotifyFilters.FileName | NotifyFilters.DirectoryName | NotifyFilters.Size;
fswArr[i].Created += new FileSystemEventHandler(this.fileSystemWatcher_EventHandle);
fswArr[i].Deleted += new FileSystemEventHandler(this.fileSystemWatcher_EventHandle);
fswArr[i].Changed += new FileSystemEventHandler(this.fileSystemWatcher_EventHandle);
fswArr[i].Renamed += new RenamedEventHandler(this.fileSystemWatcher_Renamed);
fswArr[i].EnableRaisingEvents = true;
}
}
else
{
MessageBox.Show("您尚未选择任何监控路径!");
return;
}
}
}
/// <summary>
/// 停止按钮
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void stop_tsbtn_Click(object sender, EventArgs e)
{
foreach (FileSystemWatcher fsw in fswArr)
{
fsw.EnableRaisingEvents = false; //获取或设置一个值,该值指示是否启用此组件。
}
}
/// <summary>
/// 文件监听事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void fileSystemWatcher_EventHandle(object sender, FileSystemEventArgs e)
{
if (this.fileEventLog_lvw.InvokeRequired)
{
this.fileEventLog_lvw.Invoke(new setLogTextDelegate(setLogText), new object[] { e });
}
}
/// <summary>
/// 重命名事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void fileSystemWatcher_Renamed(object sender,RenamedEventArgs e)
{
if (this.fileEventLog_lvw.InvokeRequired)
{
this.fileEventLog_lvw.Invoke(new renamedDelegate(setRenamedLogText), new object[] { e });
}
}
private void setLogText(FileSystemEventArgs e)
{
//Todo
}
private void setRenamedLogText(RenamedEventArgs e)
{
//Todo
}
总结:
1.有些时候只想监听文件发生修改的动作,但是有些时候文件修改了会触发好几次监听动作。后来发现这个和 设置的NotifyFilter 属性有关,上文中第二种方法中的 NotifyFilter 属性设置成,NotifyFilters.FileName | NotifyFilters.DirectoryName | NotifyFilters.Size就不会出现这种问题,但是如果再加上LastWriteTime这个属性,那么就会触发多次修改。因为之前监听到的是文件Size的变化事件,保存动作完成后会触发LastWriteTime事件,所以才会有多次触发。因此,监听的类型不是越多越好,要根据自己的实际需求进行选择