2009-01-30 60 views
6

這樣做的任何問題?c#我如何計算文本文件中的行

int i = new StreamReader("file.txt").ReadToEnd().Split(new char[] {'\n'}).Length 
+1

重複:http://stackoverflow.com/questions/119559/c-determine-the-number-of-lines-within-a-text-file – Juliet 2009-01-30 18:58:19

回答

39

你發佈的方法不是特別好。讓我們打破了這種分開:

// new StreamReader("file.txt").ReadToEnd().Split(new char[] {'\n'}).Length 
//  becomes this: 
var file = new StreamReader("file.txt").ReadToEnd(); // big string 
var lines = file.Split(new char[] {'\n'});   // big array 
var count = lines.Count; 

你實際持有在內存中這個文件兩次:一次讀取所有的行,一旦將其分割成一個數組。垃圾收集器討厭這一點。

如果你喜歡一個襯墊,你可以寫System.IO.File.ReadAllLines(filePath).Length,但是它仍然可以檢索數組中的整個文件。如果你不打算保持陣列,那麼這樣做沒有意義。

更快的解決辦法是:

int TotalLines(string filePath) 
{ 
    using (StreamReader r = new StreamReader(filePath)) 
    { 
     int i = 0; 
     while (r.ReadLine() != null) { i++; } 
     return i; 
    } 
} 

上述代碼持有(至多)在任何給定時刻在存儲器中一個文本行。只要線路相對較短,它就會很有效率。

6

好了,有了這樣做的問題是,你對大文件執行此操作時分配的內存很多

我寧願逐行閱讀文件並手動增加計數器。這可能不是一條線,但它更有記憶效率。

或者,您可以將數據加載到大小相同的塊中,然後計算這些塊中的換行符。這可能是最快的方法。

2

當然 - 它將整個流讀入內存。這很簡單,但我今天可以創建一個文件,這將很難實現。

一次讀取一個字符並在換行符上增加您的計數。

編輯 - 一些快速研究 後,如果您要簡潔,要閃亮的新的通用的感覺,這樣考慮:

public class StreamEnumerator : IEnumerable<char> 
{ 
    StreamReader _reader; 

    public StreamEnumerator(Stream stm) 
    { 
     if (stm == null) 
      throw new ArgumentNullException("stm"); 
     if (!stm.CanSeek) 
      throw new ArgumentException("stream must be seekable", "stm"); 
     if (!stm.CanRead) 
      throw new ArgumentException("stream must be readable", "stm"); 

     _reader = new StreamReader(stm); 
    } 

    public IEnumerator<char> GetEnumerator() 
    { 
     int c = 0; 
     while ((c = _reader.Read()) >= 0) 
     { 
      yield return (char)c; 
     } 
    } 

    IEnumerator IEnumerable.GetEnumerator() 
    { 
     return GetEnumerator(); 
    } 
} 

它定義了一個新的類,它允許你枚舉流,那麼你的計數代碼可以看起來像這樣:

StreamEnumerator chars = new StreamEnumerator(stm); 
int lines = chars.Count(c => c == '\n'); 

它給你一個很好的簡潔lambda表達式來做(或多或少)你想要的。

我還是比較喜歡舊派:

public static int CountLines(Stream stm) 
    { 
     StreamReader _reader = new StreamReader(stm); 
     int c = 0, count = 0; 
     while ((c = _reader.Read()) != -1) 
     { 
      if (c == '\n') 
      { 
       count++; 
      } 
     } 
     return count; 
    } 

NB:Environment.NewLine版本作爲練習留給讀者

+0

這不會搜索Environment.NewLine工作時,通常是兩個字符的字符串(CrLf)。 – spoulson 2009-01-30 18:50:34

+0

他有正確的想法。那麼如何使用RegEx來搜索Environment.NewLine的實例呢? – JMD 2009-01-30 18:59:47

-1

假設該文件存在,你可以打開它,將工作。

這不是很可讀或安全......

4

如果你正在尋找一個簡短的解決方案,我可以給你一個班輪,至少把你從拆分結果:

int i = File.ReadAllLines("file.txt").Count; 

但是,這與將原始大文件讀入內存的問題相同。您應該真正使用流讀取器並在讀取它們時計算換行符,直到您到達文件末尾。

0

Mayby this?

string file = new StreamReader("YourFile.txt").ReadToEnd(); 
string[] lines = file.Split('\n'); 
int countOfLines = lines.GetLength(0));