7

我想定期读取一个也在写入的日志文件。该程序将定期读取日志文件内容并对其进行解析以提取一些值。但我不想每次都阅读整个文件。

有没有办法从特定行开始读取文件?

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

有没有一种有效的方法来做到这一点?日志文件将增长到大约 100MB,我需要大约每 5 秒读取一次。因此,每次读取完整文件的效率不会那么高。

非常感谢任何建议。

4

4 回答 4

5

我认为您正在寻找这个,其中偏移量将是您想要回溯的程度。参考:MSDN

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

现在,文件流指向您将“偏移”设置为的文件中的任何位置,您可以从那里读取。

于 2013-05-01T13:52:27.073 回答
3

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

var fs = new FileStream(path,FileMode.Open,FileAccess.Read, FileShare.ReadWrite);
于 2013-05-01T13:44:42.083 回答
3

Seek 可以很好地做到这一点。但我想提供其他前进的方式。

    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);
    }
于 2013-05-01T15:06:00.160 回答
2

对于快速而肮脏的东西,我使用它。在这种情况下,它是一个日志转储——我并不关心我得到了多少行,我只想要最后一堆(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.

这是一个有点坚韧不拔的实现,但它非常快,这就是我使用它的原因。

于 2013-05-01T13:55:00.320 回答