c# -定期读取文件最后一部分的最有效方法

本文关键字:一部分 有效 方法 最后 文件 读取 | 更新日期: 2023-09-27 18:11:52

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

是否有一种从特定行开始读取文件的方法?

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

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

任何建议都非常感谢。

c# -定期读取文件最后一部分的最有效方法

我想你在寻找这个,偏移量将是你想要回溯的程度。参考:MSDN

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

现在文件流指向文件中你设置的'offset'的位置,你可以从那里读取

如果日志只是附加的,您可以尝试在没有锁的情况下以只读模式打开文件。这样其他进程可以在你读它的时候写它。

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

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);
    }

对于一些快速和肮脏的东西,我使用这个。在本例中,它是一个日志转储-我并不真正关心我得到多少行,我只想在末尾(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

这是一个有点粗糙的实现,但它非常快,这就是为什么我使用它。