限制txt文件的行

时间:2016-01-29 10:47:17

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

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

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

2 个答案:

答案 0 :(得分:2)

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

  1. 将整个文件读入内存,切掉不需要的部分,然后将其写回来
  2. 逐行读取文件,忽略前X行以达到阈值以下,写出您想要的行到临时文件。过滤完所需的所有行后,将临时文件移到现有文件的顶部。
  3. 还有其他选择:

    • 使用支持任意删除的文件格式/数据结构,如数据库。
    • 使用滚动日志,在现有文件变得太大时启动新文件。有很多现有的日志记录库可以通过一些配置为您提供开箱即用的功能。
    • 停止阅读整个文件,只读取它的结尾。当然,这有好处和缺点。好处是你可以保存文件大小。缺点是如果你需要保证读取最后N行,那么确保这需要更多的工作。

答案 1 :(得分:1)

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