我想定期读取一个正在写入的日志文件。 程序将定期读取日志文件内容并解析它以提取一些值。但我不想每次都阅读整个文件。C# - 定期读取文件最后部分的最有效方法
有没有办法从特定的行向前读取文件?
例如在第一次读取文件时有100行。我注意到这个值,下次我读取时,我从第100行开始读取并存储当前文件的行号。
有没有一种有效的方法来做到这一点? 日志文件将增长到大约100MB,并且我需要每隔5秒阅读一次。所以每次读完整个文件都不是那么高效。
任何建议,非常感谢。
我想定期读取一个正在写入的日志文件。 程序将定期读取日志文件内容并解析它以提取一些值。但我不想每次都阅读整个文件。C# - 定期读取文件最后部分的最有效方法
有没有办法从特定的行向前读取文件?
例如在第一次读取文件时有100行。我注意到这个值,下次我读取时,我从第100行开始读取并存储当前文件的行号。
有没有一种有效的方法来做到这一点? 日志文件将增长到大约100MB,并且我需要每隔5秒阅读一次。所以每次读完整个文件都不是那么高效。
任何建议,非常感谢。
如果仅附加日志,则可以尝试在不锁定的情况下以只读模式打开文件。这样,其他进程可以在读取时写入它。
var fs = new FileStream(path,FileMode.Open,FileAccess.Read, FileShare.ReadWrite);
如果你还记得文件的长度,你可能可以在下一次阅读时“查找”该位置。 – JosephHirn 2013-05-01 13:53:51
对于快速和肮脏的东西,我用这个。在这种情况下,它是一个日志转储 - 我真的不关心有多少行我得到的,我只是想一堆末(numBytes
):
cmdLogReader = new System.IO.StreamReader(cmdLogFileIn);
if (cmdLogReader.BaseStream.Length < (numBytes - 1)) {
return cmdLogReader.ReadToEnd;
} else {
cmdLogReader.BaseStream.Seek(-numBytes, System.IO.SeekOrigin.End);
cmdLogReader.ReadLine();
return cmdLogReader.ReadToEnd;
}
你总是可以保存BaseStream.Length
的开头和用它来计算下次要走多远(即:numBytes
变为BaseStream.Length - previousBaseStreamLength
或其他),这将使顺序调用抓住自上次读取后添加的任何内容。
如果你这样做,你可能不得不跳过ReadLine
的调用,因为它真的只有在回溯一个随机数后才移动到最近的一行。如果你知道你将要登陆一个界限线,那么你可以只用ReadToEnd
。
这是一个坚韧不拔的实现,但它非常快,这就是为什么我使用它。
谢谢。我不知道BaseStream.Length属性并使用此方法读取文件。我会看看这种方法。 – madu 2013-05-01 14:10:19
寻求可以做到这一点。但我想提供其他方法。
public static void Read()
{
var fs = new FileStream(@"G:\test.txt", FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
int lastReadCount = 0;
while (true)
{
var totalCountOfFile = fs.Length;
if (lastReadCount < totalCountOfFile)
{
var buffer = new byte[1024];
int count = fs.Read(buffer, 0, buffer.Length);
lastReadCount += count;
Display(buffer);
}
Thread.Sleep(5000);
}
}
private static void Display(byte[] buffer)
{
var text = Encoding.UTF8.GetString(buffer.Where(p=>p != 0).ToArray());
Console.Write(text);
}
你可能看Tail.NET http://www.codeproject.com/Articles/7568/Tail-NET – itsmatt 2013-05-01 13:43:43
你可以分区的文件分割成多个文件或数据库用于这一目的。虽然,我不知道只有100MB文件提供了多少好处。流往往有开始索引。为什么不使用它? – 2013-05-01 13:46:10