2012-02-29 58 views
2

我正在开发一个小型C#应用程序,用于扫描包含特定关键字的行的日志文件,并在找到其中一个关键字时提醒用户。这个日志可能非常大(在最坏的情况下是几千兆字节),但日志中唯一与我相关的行是在我的应用程序运行时添加到日志中的日志。捕获对日志文件的更改

有没有一种方法可以捕获每个文本行被追加到文件,而不必担心已经存在的文件内容?

我已经发现了FileSystemWatcher类,同时寻找解决的办法,虽然这似乎伟大的通知我有新的内容从日志中获取,它似乎并没有帮助你告诉我什么已添加

+1

请参阅:http://stackoverflow.com/questions/452902/how-to-read-a-text-file-reversely-with-iterator-in-c-sharp – 2012-02-29 02:14:04

+0

请不要在“ C#“等等。这就是标签的用途。 – 2012-02-29 03:40:57

回答

4

如果您保持FileStream处于Read模式(当然允许编写器),您应该能够首先扫描整个文件并等待最后直到FSW通知您文件已被修改。

如果文件被删除,请注意重置读取线程,例如,如果您正在拖拽的日志文件被滚动。

在这里,我拼凑的示例 - 运行它,并在运行时,在记事本编辑C:\Temp\Temp.txt并保存:

public static void Main() 
    { 
     var lockMe = new object(); 
     using (var latch = new ManualResetEvent(true)) 
     using (var fs = new FileStream(@"C:\Temp\Temp.txt", FileMode.OpenOrCreate, FileAccess.Read, FileShare.ReadWrite)) 
     using (var fsw = new FileSystemWatcher(@"C:\Temp\")) 
     { 
      fsw.Changed += (s, e) => 
           { 
            lock (lockMe) 
            { 
             if (e.FullPath != @"C:\Temp\Temp.txt") return; 
             latch.Set(); 
            } 
           }; 
      using (var sr = new StreamReader(fs)) 
       while (true) 
       { 
        latch.WaitOne(); 
        lock (lockMe) 
        { 
         String line; 
         while ((line = sr.ReadLine()) != null) 
          Console.Out.WriteLine(line); 
         latch.Set(); 
        } 
       } 
     } 
    } 
+0

这对于一个小文本文件非常有用,但由于初始扫描需要花费几分钟的时间处理127 MB样本。我不认为有任何方法可以避免浏览整个文件? – Silen 2012-02-29 03:09:05

+1

在创建StreamReader之前,只需在其中添加一个'fs.Seek(0,SeekOrigin.End);'。 – 2012-02-29 03:13:03

+0

完美的作品,非常感谢你! – Silen 2012-02-29 03:25:03

0

最有效的解决方案(如果您的应用程序需要它),是编写一个文件钩子驱动程序来捕获文件的所有写入权限。该驱动程序可能会告诉您哪些字节已更改。如果你不想用C/C++编写驱动程序,也许你可以使用EasyHook。 EasyHook非常棒,因为如果您知道写入日志文件的确切应用程序,您可以编写一个非常简单的用户模式钩子(检查他在CodePlex上的示例)。如果您不知道应用程序的名称,则可能需要编写一个内核挂钩(使用EasyHook可以更容易)。

0

this question类似,但您需要记录旧文件大小。然后,而不是追求10换行符,只是寻求大小的差异。尽管如此,你必须小心编码。

+0

更简单的解决方案;] – Jason 2012-02-29 02:20:37

0

而不是从文件中读取文本(我假设你是这样做),读取文件的字节。如果您可以假定写入文件将始终追加,并且您知道文件的文本编码,那么您只需读取以原始文件的文件大小开始的字节。然后使用适当的编码将字节转换为文本。

+0

嗯,日志确实总是被追加,所以这似乎是一个可靠的解决方案,以避免贯穿整个文件。去尝试一下。 – Silen 2012-02-29 03:17:04