如何从开放流中检测文件重命名

时间:2011-05-19 13:34:54

标签: c# .net file-io windows-services

问题:

是否可以检测何时重命名了具有打开的FileStream的文件。

案例:

我正在尝试监视应用程序的日志,我从日志文件中读取,因为我不想干扰日志记录本身。

在文件滚动之前,这很有用。我的应用程序不断读取重命名的文件。

尝试使用FileSystemWatcher来检测滚动,但有时会收到很多事件,有时候我没有,所以这不是一个很好的解决方案(日志文件也可以驻留在网络共享可能是使用FSW的额外阻碍。)

如果我能找到哪个文件(名称)我有一个打开的句柄,我可以将其与_fileName进行比较,但我不知道如何做到这一点。

我还有其他可以探索的选择吗?

代码:

这是我的文件监控类的简化版本:

public class MonitorFile
{
    private String _fileName = String.Empty;
    private bool _stopMonitoring = false;

    public MonitorFile(string fileName)
    {
        _fileName = fileName;
    }

    // Simplified method
    public void StartMonitoring()
    {
        using (var reader = new StreamReader(
                    new FileStream(
                        _monitorFileName,
                        FileMode.Open,
                        FileAccess.Read,
                        FileShare.Delete | FileShare.ReadWrite)))
        {
            while (!_stopMonitoring)
            {
                Thread.Sleep(500);

                while ((line = reader.ReadLine()) != null)
                {
                    //...Do stuff with the lines
                }
            }
        }
    }
}

3 个答案:

答案 0 :(得分:1)

您可以从监视文件路径中提取目录名称。 然后在readLine循环之后: 获取目录中的文件列表,按上次更新日期排序 取列表中的第一项 将它与您正在阅读的文件名进行比较,如果它们不同则更新您的阅读器

这是假设只有目录中的文件才是日志文件,并且您总是希望从最近更新的文件中读取文件

答案 1 :(得分:1)

有一个MSDN示例显示how you can obtain a file name from a file handle(您可以使用Win32 API通过Handle的{​​{1}}属性访问),但我怀疑这种方法适用于文件远程网络共享。

在一般情况下,你可能会失败。

答案 2 :(得分:0)

假设滚动文件具有不同/更新的创建日期,您可以在上一次监视读取期间比较文件中的创建日期吗?访问和修改时间可能没有用,但创建日期可能有用。

您可以尝试System.IO.File.GetCreationTime,但可能还有其他影响因素:

  

NTFS格式的驱动器可能会缓存文件   元信息,例如文件创建时间,   在短时间内,这是   被称为“文件隧道”。作为一个   结果,可能有必要   明确设置a的创建时间   文件如果你被覆盖或   替换现有文件。