如何在C#中从文本文件中获取特定行?

3

我正在使用C#工作,有一个大文本文件(75MB),我想保存与正则表达式匹配的行。

我尝试使用StreamReader和ReadToEnd读取文件,但它会占用400MB的内存,并且再次使用时会创建内存不足异常。

然后我尝试使用File.ReadAllLines():

string[] lines = File.ReadAllLines("file");

StringBuilder specialLines = new StringBuilder();


foreach (string line in lines)

 if (match reg exp)

  specialLines.append(line);

这很不错,但当我的函数结束时,所占用的内存并没有被清除,留下了 300MB 的已用内存,只有在重新调用函数并执行以下代码段时: string[] lines = File.ReadAllLines("file"); 我才看到内存减少到大约 50MB 左右,然后重新分配回 200MB。
怎么样可以清除这些内存或以不同的方式获取所需行?
4个回答

6
        var file = File.OpenRead("myfile.txt");
        var reader = new StreamReader(file);
        while (!reader.EndOfStream)
        {
            string line = reader.ReadLine();
            //evaluate the line here.
        }
        reader.Dispose();
        file.Dispose();

1
另外,不要忘记处理 FileStreamStreamReader 对象。 - Matt Brunell
3
你不需要自己创建流,StreamReader 构造函数可以直接使用文件名。此外,你不应该使用 EndOfStream 来检查是否到达了文件末尾:由于 StreamReader 缓冲数据,所以在 StreamReader 返回所有行之前,流位置可能已经到达了末尾。 - Thomas Levesque
你需要将循环改为:while(reader.Peek() >-1) { string line = reader.ReadLine(); //etc } 原因是Thomas提到的原因,而不是使用!reader.EndOfStream。 - Tom
1
你应该使用 using 块,否则如果在调用 Dispose 之前发生异常,文件将不会被关闭。 - Thomas Levesque

2

您需要流式传输文本,而不是将整个文件加载到内存中。以下是一种使用扩展方法和Linq来实现的方法:

static class ExtensionMethods
{
    public static IEnumerable<string> EnumerateLines(this TextReader reader)
    {
        string line;
        while((line = reader.ReadLine()) != null)
        {
            yield return line;
        }
    }
}

...

var regex = new Regex(..., RegexOptions.Compiled);
using (var reader = new StreamReader(fileName))
{
    var specialLines =
        reader.EnumerateLines()
              .Where(line => regex.IsMatch(line))
              .Aggregate(new StringBuilder(),
                         (sb, line) => sb.AppendLine(line));
}

1
+1 - 我会加上一条提示,即.NET 4.0已经实现了类似的方法。 - ChaosPandion
@ChaosPandion,你是指 File.ReadLines 吗?好的,我以前从没注意过它... - Thomas Levesque
没错。回想起来,我可能应该提到它。 :) - ChaosPandion

1

0
你应该使用Enumerator模式来保持内存占用低,以防文件很大。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接