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

如何实时监控文件系统变更并获取未关闭文件的追加内容?

文件系统实时监控未关闭文件追加内容的解决方案

问题背景

我需要开发应用识别文件系统的变更,尤其是文件创建与更新操作。这些文本文件由另一应用创建,该应用完成前不会关闭文件,但我需要获取文件的追加内容。

使用FileSystemWatcher监控时遇到以下问题:

  • 若写入文件的应用未关闭文件(且缓冲区未填满),文件内容不会实时更新到磁盘,FileSystemWatcher无法捕获变更。
  • 执行Write-VolumeCache命令无效,但用记事本打开文件后,FileSystemWatcher能立即收到更新事件——说明存在某种机制可触发写入应用刷新缓冲区。
  • 仅知晓文件的部分路径和名称,必须监控指定目录及其子目录,每秒遍历所有文件开销过大。

补充信息:

  • PowerShell的Get-Content -wait <file>可实时显示文件更新内容,同时能触发FileSystemWatcher的事件。
  • 尝试过监控文件创建事件后,以流的形式打开文件读取内容,但不知道如何捕获文件关闭事件以释放流资源。

解决方案

1. 记事本触发刷新的核心机制

记事本打开文件时,会以共享读模式(FileShare.ReadWrite)访问文件,Windows文件系统会因此强制写入应用将内核缓冲区中的数据刷新到磁盘——这并非依赖特定命令,而是文件共享访问触发的系统缓存同步机制。你不需要执行外部命令,只需模拟这种共享访问逻辑即可触发刷新。

2. 基于文件流的实时跟踪方案

监控到文件创建事件后,以共享读写模式打开文件流,持续跟踪读取位置,定时读取新增内容:

  • 每次读取前记录当前流的Position,下次读取从该位置开始,避免重复读取旧内容。
  • 通过监听FileSystemWatcher的Deleted事件,或定期检查文件是否存在,来触发流资源的释放。
  • 处理文件锁定异常:若写入应用暂时独占文件,捕获异常后重试即可。

示例伪代码:

// 存储正在跟踪的文件流
Dictionary<string, FileStream> trackedStreams = new Dictionary<string, FileStream>();

// 处理文件创建事件
void OnFileCreated(object sender, FileSystemEventArgs e)
{
    try
    {
        // 以共享读写模式打开文件,避免阻塞写入应用
        var stream = new FileStream(e.FullPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
        trackedStreams.Add(e.FullPath, stream);
        // 启动后台任务持续读取新增内容
        Task.Run(() => ReadStreamContinously(stream, e.FullPath));
    }
    catch (Exception ex)
    {
        // 处理文件锁定等异常,可添加重试逻辑
    }
}

async Task ReadStreamContinously(FileStream stream, string filePath)
{
    var reader = new StreamReader(stream);
    long lastReadPosition = 0;
    while (trackedStreams.ContainsKey(filePath))
    {
        stream.Position = lastReadPosition;
        string newContent = await reader.ReadToEndAsync();
        if (!string.IsNullOrEmpty(newContent))
        {
            // 处理获取到的新增内容
            Console.WriteLine(newContent);
            lastReadPosition = stream.Position;
        }
        await Task.Delay(1000); // 每秒检查一次新增内容
    }
    // 释放资源
    reader.Dispose();
    stream.Dispose();
}

// 处理文件删除事件,释放对应流
void OnFileDeleted(object sender, FileSystemEventArgs e)
{
    if (trackedStreams.ContainsKey(e.FullPath))
    {
        trackedStreams.Remove(e.FullPath);
    }
}

3. 简化方案:借鉴Get-Content -Wait逻辑

Get-Content -Wait的核心逻辑是定期检查文件大小,当文件大小超过上次记录值时,读取新增部分。这种方式不需要维持长连接流,实现更简单,适合对实时性要求不极致的场景:

  • 监控到文件创建后,记录初始文件大小。
  • 每秒检查一次文件大小,若有增长,读取从上次记录位置到当前文件末尾的内容。

关键注意事项

  • 坚持用FileSystemWatcher监控创建事件,只跟踪已创建的文件,避免全目录遍历的高开销。
  • 务必处理资源释放,防止因文件被删除/关闭导致的内存泄漏。
  • 针对文件锁定场景,添加重试逻辑,避免单次失败就放弃跟踪。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 00:32:35