【问题标题】:Limit lines of a txt file [closed]txt文件的限制行[关闭]
【发布时间】:2016-05-07 01:44:49
【问题描述】:

我有一个文本文件,我使用 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";
    }
}

我已经尝试调试它并且我没有从阅读代码中得到任何异常。也许问题是我试图将所有文本放在一个文本块中。

【问题讨论】:

  • 你必须重写整个文件。所以我只会偶尔这样做。但是,如果应用程序崩溃了,为什么还要阅读整个文件呢?你可以简单地少读一点。
  • 或者你可以修复崩溃的代码。 “文件变得太大”是什么意思?是否超过 2GB?有例外吗?它发生在哪里?代码在哪里?无论文件大小如何,简单地调用 WriteLineAsync 都不会失败。
  • 或许可以考虑使用多个较小的文件
  • PS,听起来你几乎是在尝试登录。与其重新发明轮子,不如使用许多日志库之一,如 log4net、NLog 和滚动文件选项

标签: c# uwp windows-10-mobile visual-studio-2015


【解决方案1】:

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

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

还有其他选择:

  • 使用支持任意删除的文件格式/数据结构,例如数据库。
  • 使用滚动日志,当现有文件变得太大时启动一个新文件。有很多现有的日志库可以为您提供开箱即用的功能,只需进行一些配置。
  • 停止读取整个文件,只读取它的结尾。诚然,这既有好处也有坏处。好处是您可以根据需要保持文件大小。不利的一面是,如果您需要保证读取最后 N 行,则需要做更多的工作才能确保这一点。

【讨论】:

  • 3.将其拆分为多个(历史)文件 4. 少读而不是整个文件
  • 更好的是,什么都不做。添加一个日志库并让它滚动
【解决方案2】:

如果您知道需要记录的行的最大长度,并且不介意从日志字符串中删除 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!");
}

【讨论】:

    猜你喜欢
    • 2018-09-06
    • 1970-01-01
    • 1970-01-01
    • 2018-08-10
    • 2021-02-16
    • 1970-01-01
    • 2020-02-10
    • 1970-01-01
    • 2023-03-23
    相关资源
    最近更新 更多