2013-05-01 64 views
5

我想定期读取一个正在写入的日志文件。 程序将定期读取日志文件内容并解析它以提取一些值。但我不想每次都阅读整个文件。C# - 定期读取文件最后部分的最有效方法

有没有办法从特定的行向前读取文件?

例如在第一次读取文件时有100行。我注意到这个值,下次我读取时,我从第100行开始读取并存储当前文件的行号。

有没有一种有效的方法来做到这一点? 日志文件将增长到大约100MB,并且我需要每隔5秒阅读一次。所以每次读完整个文件都不是那么高效。

任何建议,非常感谢。

+2

你可能看Tail.NET http://www.codeproject.com/Articles/7568/Tail-NET – itsmatt 2013-05-01 13:43:43

+0

你可以分区的文件分割成多个文件或数据库用于这一目的。虽然,我不知道只有100MB文件提供了多少好处。流往往有开始索引。为什么不使用它? – 2013-05-01 13:46:10

回答

3

我认为你正在寻找这个,其中抵消将是多少你想要回溯。参考:MSDN

using (FileStream fs = new FileStream(filepath, FileMode.Open, FileAccess.Read)) 
{ 
    fs.Seek(offset, SeekOrigin.End); 
} 

现在FILESTREAM指向然而早您设置的文件在“偏移”是的,你可以从那里读取。

+0

...哈,我两分钟太慢了;) – 2013-05-01 13:58:22

+0

@bland谢谢。我会看看这种方法。看起来这可以为我工作。 – madu 2013-05-01 14:09:11

2

如果仅附加日志,则可以尝试在不锁定的情况下以只读模式打开文件。这样,其他进程可以在读取时写入它。

var fs = new FileStream(path,FileMode.Open,FileAccess.Read, FileShare.ReadWrite); 
+0

如果你还记得文件的长度,你可能可以在下一次阅读时“查找”该位置。 – JosephHirn 2013-05-01 13:53:51

1

对于快速和肮脏的东西,我用这个。在这种情况下,它是一个日志转储 - 我真的不关心有多少行我得到的,我只是想一堆末(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

这是一个坚韧不拔的实现,但它非常快,这就是为什么我使用它。

+0

谢谢。我不知道BaseStream.Length属性并使用此方法读取文件。我会看看这种方法。 – madu 2013-05-01 14:10:19

1

寻求可以做到这一点。但我想提供其他方法。

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); 
    } 
相关问题