【问题标题】:Read Changes on a text file dynamically c#动态读取文本文件的更改c#
【发布时间】:2013-10-14 07:31:13
【问题描述】:

我有一个程序不断将其日志写入文本文件。 我没有它的源代码,所以我不能以任何方式修改它,它也受到 Themida 的保护。

我需要读取日志文件并根据文件的内容执行一些脚本。 我无法删除该文件,因为不断写入该文件的程序已锁定该文件。 那么读取文件并仅读取文件的新行的更好方法是什么? 保存最后一行的位置?或者有什么东西可以在 C# 中解决它?

【问题讨论】:

标签: c# file text


【解决方案1】:

也许使用FileSystemWatcher 以及使用 FileShare 打开文件(因为它正在被另一个进程使用)。 Hans Passant 为这部分提供了一个很好的答案here

var fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); 
        using (var sr = new StreamReader(fs)) {
            // etc...
        } 

看看这个question 和接受的答案,这可能也有帮助。

【讨论】:

    【解决方案2】:
    using (var fs = new FileStream("test.txt", FileMode.Open, FileAccess.Read, FileShare.ReadWrite | FileShare.Delete))
    using (var reader = new StreamReader(fs))
    {
        while (true)
        {
            var line = reader.ReadLine();
    
            if (!String.IsNullOrWhiteSpace(line))
                Console.WriteLine("Line read: " + line);
        }
    }
    

    我测试了上面的代码,如果你想一次读一行,它就可以工作。唯一的问题是,如果在完成写入之前将该行刷新到文件中,那么您将分多个部分读取该行。只要日志系统一次写入每一行就应该没问题。

    如果不是,那么您可能希望读取缓冲区而不是使用 ReadLine,因此您可以通过检测每个 Environment.NewLine 子字符串自己解析缓冲区。

    【讨论】:

    • 也是一个很好的答案,它会等到整行可用,但它会连续锁定文件(这不一定是问题)。
    • 如果 line == NullOrWhiteSpace 则添加一点睡眠。
    【解决方案3】:

    您可以在一个紧密的循环中继续调用 ReadToEnd()。即使到达文件末尾,它也只会返回一个空字符串“”。如果将更多数据写入文件,它将在后续调用中获取。

    while (true)
    {
        string moreData = streamReader.ReadToEnd();
        Thread.Sleep(100);
    }
    

    请记住,您可能会以这种方式阅读部分行。此外,如果您正在处理非常大的文件,您可能需要另一种方法。

    【讨论】:

    • 这是一个很好的答案,非常简单。我的更好,因为该文件大部分时间都没有被读锁定。
    【解决方案4】:

    使用 filesystemwatcher 检测更改并使用上次读取位置获取新行并查找文件。

    http://msdn.microsoft.com/en-us/library/system.io.filestream.seek.aspx

    【讨论】:

      【解决方案5】:

      日志文件正在“持续”更新,因此您真的不应该在每次文件更改时使用FileSystemWatcher 来引发事件。这将持续触发,并且您已经知道它会非常频繁地更改。

      我建议使用计时器事件来定期处理文件。 Read this SO answer 获取使用 System.Threading.Timer1 的良好模式。保持文件流打开以供阅读或每次重新打开,Seek 到最后一次成功读取的结束位置。 “最后一次成功读取”是指您应该封装完整日志行的读取和验证。成功读取并验证日志行后,您就有了下一个 Seek 的新位置。

      1 请注意,System.Threading.Timer 将在系统提供的线程上执行,该线程由ThreadPool 保持在业务中。对于短任务,这比专用线程更可取。

      【讨论】:

      • 你能说得更详细些吗?我或多或少有同样的问题。我有一个大文件(60MB),它一直是从机器上写入的。现在我应该读取其中写入的所有数据。我也可以不时删除文件吗?
      【解决方案6】:

      在另一个帖子c# continuously read file 上使用这个答案。

      这个非常有效,它每秒检查一次文件大小是否发生变化。因此文件通常不会因此而被读锁定。

      其他答案非常有效且简单。他们中的一些人会连续读取锁定文件,但这对大多数人来说可能不是问题。

      【讨论】:

        猜你喜欢
        • 2020-06-22
        • 1970-01-01
        • 2021-03-27
        • 1970-01-01
        • 2021-03-10
        • 2015-05-16
        • 1970-01-01
        相关资源
        最近更新 更多