2014-10-19 112 views
0

我正在用StreamReader讀取文件的.NET應用程序中編寫文件解析器。要解析的文件以標頭開頭,標頭以"<eoh>"結尾。我想要從開始直到該字符串讀取或忽略所有內容。實際數據在此之後開始。用StreamReader讀取到某個字符串

該文件不是基於行的。一切只有通過這樣的標記字符串進行分配。所以我不能使用ReadLine。

如何在不讀取一個字符的情況下執行狀態機來識別標記工作字符?我正在尋找一種方法,如StreamReader.SkipUntilAfter(string)StreamReader.ReadUntil(string)

哦,這個項目仍然使用.NET 2.0,所以在這裏不需要LINQ。儘管如果有人建議使用它,我可能會解決這個問題。

+0

如果文件是基於行的,你可以使用'File.ReadLines'和LINQ(f.e。'SkipWhile','TakeWhile')。 – 2014-10-19 19:53:20

+0

您可以使用while((line = reader.ReadLine())!= null){//只讀後行.Equals(「」)} – Crasher 2014-10-19 19:54:52

+0

更新的問題:它不是基於行的。標記可能出現在一行的中間。然後我已經閱讀了部分數據。而StreamReader無法在任何地方尋找或尋找。 – ygoe 2014-10-19 19:57:25

回答

1

TextReader s一般已經閱讀只是逐字。他們使用一個緩衝區,這樣更快,但是對於StreamReader的緩衝沒有什麼不同,只是直到前面讀取並拉動到<eoh>。出於同樣的原因,直到在該標題之後跳過也沒有更好的方法。絕對最佳情況將是一個內置函數,它只是在視覺上抽象出底層代碼,所以這不是特別有用。

如果您因爲某種原因不相信我,here's the source code

另外,值得注意的是,無論使用什麼,您都必須逐個字符地查看。即使你有辦法將它們拉入內存中,比較兩個string也是逐個字符的操作。所以你不會保存任何東西。

就我個人而言,我只是喜歡這樣的東西。它需要TextReader和結尾字符串,並讀取reader,直到找到eoh。然後它返回一個bool它是否找到標記。

public bool SkipUntilAfterHeader(TextReader reader, string eoh) 
{ 
    int eohGuessIndex = 0; 
    int next; 

    while ((next = reader.Read()) != -1) 
    { 
     char c = (char)next; 

     if (c == eoh[eohGuessIndex]) 
     { 
      eohGuessIndex++; 
      if (eohGuessIndex == eoh.Length) 
      { 
       return true; 
      } 
     } 
     else 
     { 
      eohGuessIndex = 0; 
     } 
    } 

    return false; 
} 

我不確定什麼.NET 2.0有或沒有,所以我寫了一些從頭開始,可能或可能不必。但是,性能不應該受到影響。這方面的一個很好的方面是,您還可以輕鬆地添加一個StringBuilder以及一個out參數,該參數可以傳遞標頭信息,以備日後使用。

然後,使用非常簡單。

public void ReadFile(string path) 
{ 
    using (StreamReader reader = new StreamReader(path)) 
    { 
     if (SkipUntilAfterHeader(reader, "<eoh>")) 
     { 
      // read file 
     } 
     else 
     { 
      // corrupt file 
     } 
    } 
} 

但是,實際上,讀取整個文件並僅返回相關部分可能會更容易。與可讀性相比,這取決於性能有多重要。

而在經典的糟糕的形式,請注意,我沒有測試 - 甚至編譯 - 這一切。但即使不起作用,它也應該相對容易修復。

+0

這將工作,但按字符讀取的字節比StreamReader內部的CPU密集得多。 – usr 2014-10-19 20:52:46

+0

@usr不,實際上不是。查看參考源實現['Read'](http://referencesource.microsoft.com/mscorlib/a.html#5d81175d2e6d320e)及其對['ReadLine']的實現(http://referencesource.microsoft的.com/mscorlib程序/ a.html#a4ada5f765646068)。 「ReadLine」實際上與我一樣,只是更加優化一點而已。但在這裏你什麼也做不了。他們都在內部使用緩衝區,所以它主要只是內存讀取。 'List <>'很容易做得更好,但是我選擇了更多可擴展的選項。 – 2014-10-19 20:57:30

+1

您的熱循環比StreamReader可以做的要少得多,因爲它可以直接使用其內部緩衝區。爲每個字符調用Read是你在基準測試中會注意到的。此外,列表添加和刪除會增加開銷。我會說你的速度比原生版慢3倍以上。 – usr 2014-10-19 21:00:56