动态读取文本文件的更改c#

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

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

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

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

看看这个问题和接受的答案也可能有所帮助。

 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子字符串来自己解析缓冲区。

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

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

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

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

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

日志文件正在“持续”更新,因此每次文件更改时,您都不应该使用FileSystemWatcher来引发事件。 这将持续触发,你已经知道它会经常变化。

我建议使用计时器事件来定期处理文件。 阅读此SO答案以获得使用System.Threading.Timer 1的良好模式。 保持文件流打开以便阅读或每次重新打开并查找上次成功阅读的结束位置。 通过“上次成功读取”,我的意思是您应该封装读取和validation完整的日志行。 一旦您成功阅读并validation了日志行,那么您将获得下一个Seek的新职位。

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

在另一篇文章中使用此答案c#连续读取文件 。

这个非常有效,如果文件大小已经改变,它每秒检查一次。 因此,文件通常不会被读取锁定。

其他答案非常有效和简单。 其中几个会连续读取文件,但对大多数人来说这可能不是问题。