2010-12-15 166 views
3

我工作在C#和我有一個大的文本文件(75MB) 我要救匹配正則表達式如何從c#中的文本文件中獲取某些行?

我試圖讀取與一個StreamReader和ReadToEnd的文件即行,但它需要的RAM 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

如何清除此內存或以不同的方式得到我需要的線?

回答

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

此外,不要忘記處理'FileStream'和'StreamReader'對象。 – 2010-12-15 15:42:50

+0

謝謝馬特。是的,你當然是對的。 – eoldre 2010-12-15 15:47:38

+3

您不需要自己創建流,StreamReader構造函數可以直接獲取文件名。另外,你不應該使用EndOfStream來檢查你是否在文件的末尾:因爲StreamReader正在緩衝數據,所以在StreamReader返回所有行之前,流的位置可能在最後。 – 2010-12-15 15:48:10

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 2010-12-15 15:42:37

+0

@ChaosPandion,你的意思是'File.ReadLines'?好現在,我從來沒有注意到它... – 2010-12-15 15:46:18

+0

這是正確的。回想起來,我可能應該提到它。 :) – ChaosPandion 2010-12-15 15:47:41

0

您應該使用枚舉器模式,讓您的內存佔用低的情況下,您的文件可能是巨大的。

相關問題