You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何获取FileSystemWatcher事件的更多详细信息及文件操作完成状态?

解决FileSystemWatcher重复事件与增强信息的方案

一、抑制重复事件

FileSystemWatcher触发多次重复事件,本质是Windows文件操作会产生多个底层通知(比如创建临时文件、写入内容、重命名最终文件等),可以通过延迟去重处理:

private readonly HashSet<string> _pendingFiles = new HashSet<string>();
private readonly Timer _processTimer = new Timer(1000); // 1秒延迟,可根据场景调整

public void InitWatcher()
{
    var watcher = new FileSystemWatcher(@"C:\YourTargetFolder");
    watcher.Created += OnFileTriggered;
    watcher.Changed += OnFileTriggered;
    _processTimer.Elapsed += ProcessPendingFiles;
    _processTimer.Start();
}

private void OnFileTriggered(object sender, FileSystemEventArgs e)
{
    lock (_pendingFiles)
    {
        _pendingFiles.Add(e.FullPath);
    }
}

private void ProcessPendingFiles(object sender, ElapsedEventArgs e)
{
    List<string> targetFiles;
    lock (_pendingFiles)
    {
        targetFiles = _pendingFiles.ToList();
        _pendingFiles.Clear();
    }

    foreach (var file in targetFiles)
    {
        if (IsFileCompleted(file))
        {
            // 执行你的业务逻辑
            Console.WriteLine($"处理就绪文件:{file}");
        }
        else
        {
            // 文件未就绪,放回待处理队列
            lock (_pendingFiles)
            {
                _pendingFiles.Add(file);
            }
        }
    }
}

二、判断文件是否完成写入/下载

核心逻辑是检查文件是否处于锁定状态——下载或复制过程中文件会被写入进程占用,无法独占访问:

private bool IsFileCompleted(string filePath)
{
    if (!File.Exists(filePath)) return false;
    
    try
    {
        // 尝试以独占读写模式打开文件,成功则说明文件已释放
        using (var stream = File.Open(filePath, FileMode.Open, FileAccess.ReadWrite, FileShare.None))
        {
            return true;
        }
    }
    catch (IOException)
    {
        // 文件被锁定,仍在写入
        return false;
    }
}

也可以结合文件大小稳定性判断:记录文件初始大小,延迟后再次检查,若连续两次大小一致,说明写入完成。

三、获取更详细的变更信息

1. 精准区分变更类型

结合ChangeType和文件状态判断真实操作:

  • 最终文件创建:Created事件触发后,通过IsFileCompleted验证通过,判定为文件下载/存入完成。
  • 完成的修改:Changed事件触发时,文件可访问且大小稳定,说明是已完成的内容修改。
  • 重命名操作:监听Renamed事件,它会提供OldFullPath和FullPath,直接明确重命名动作。

2. 读取文件详细属性

在文件就绪后,直接读取文件元数据获取额外信息:

var fileInfo = new FileInfo(filePath);
Console.WriteLine($"文件大小:{fileInfo.Length} 字节");
Console.WriteLine($"最后写入时间:{fileInfo.LastWriteTime}");
Console.WriteLine($"文件所有者:{fileInfo.GetAccessControl().GetOwner(typeof(System.Security.Principal.NTAccount))}");

四、进阶优化

  • 过滤临时文件:忽略.tmp、.part等临时后缀的文件,减少无效事件触发。
  • 底层API调用:如果需要更精细的通知,可通过P/Invoke调用Windows原生的ReadDirectoryChangesWAPI,它能返回更底层的文件操作细节(如具体的写入、删除动作),但实现复杂度更高。

内容的提问来源于stack exchange,提问作者TryingToLearn

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 20:23:15