限制 txt 文件的行数

本文关键字:文件 txt 限制 | 更新日期: 2023-09-27 18:32:29

我有一个文本文件,我使用 WriteLineAsync 方法每 30 分钟保存一行。当文件变得太大时,如果我尝试读取它,应用程序就会崩溃。我认为我可以限制文件上可写的行,因此当我添加新行时,将删除最旧的行。我该怎么做?

编辑:我使用以下代码读取文件:

StorageFile MyFile = await ApplicationData.Current.LocalFolder.GetFileAsync("LogFile.txt");
string nextLine;
using (StreamReader reader = new StreamReader(await MyFile.OpenStreamForReadAsync()))
{
    while ((nextLine = await reader.ReadLineAsync()) != null)
    {
        TextLog.Text += nextLine + "'n";
    }
}

我尝试调试它,但我在阅读代码中没有得到任何异常。也许问题是我试图将所有文本放在文本块中。

限制 txt 文件的行数

如果您确实需要对文本文件执行此操作,则必须执行以下操作之一:

  1. 将整个文件读入内存,切掉不需要的部分,然后将其写回
  2. 逐行读取文件,忽略前 X 行以低于阈值,将您想要的行写到临时文件中。过滤完所需的所有行后,将临时文件移动到现有文件的顶部。

还有其他选择:

  • 使用支持任意删除的文件格式/数据结构,例如数据库。
  • 使用滚动日志,在现有文件变得太大时启动一个新文件。有许多现有的日志记录库只需进行一些配置即可开箱即用。
  • 停止读取整个文件,只读取其末尾。当然,这既有好处也有缺点。好处是您可以根据需要保持文件的大小。缺点是,如果您需要保证读取最后 N 行,那么需要更多的工作来确保这一点。

如果您知道需要记录的行的最大长度,并且不介意从日志字符串中修剪 null,则以下解决方案可能适合您。

这是一个简单的想法,您可以在其中创建一个知道最大大小的空文件,并在每次写入的当前位置写入最大字节行长度。当您到达末尾时,您只需循环回文件的开头 - 这意味着您将在下次写入时覆盖第一个也是最旧的条目。

class MyWriter : IDisposable
{
    BinaryWriter _writer;
    readonly int _maxLineLength, _maxLines, _size;
    public MyWriter(string path, int maxLineLength, int maxLines)
    {
        _maxLineLength = maxLineLength;
        _maxLines = maxLines;
        _size = _maxLineLength * _maxLines;
        _writer = new BinaryWriter(File.Create(path));
        _writer.BaseStream.SetLength(_size);
    }
    public void Write(string str)
    {
        if (str.Length > _maxLineLength) throw new ArgumentOutOfRangeException();
        // Write the string to the current poisition in the stream.
        // Pad the rest of the line with null.
        _writer.Write(str.PadRight(_maxLineLength, ''0').ToCharArray());
        // If the end of the stream is reached, simply loop back to the start.
        // The oldest entry will then be overwritten next.
        if (_writer.BaseStream.Position == _size)
            _writer.Seek(0, SeekOrigin.Begin);
    }
    public void Dispose()
    {
        if(_writer != null)
            _writer.Dispose();
    }
}

可能用作:

using(var writer = new MyWriter("MyFile.txt", 200, 100))
{
    writer.Write("Hello World!");
}