2011-02-11 29 views
2

我需要做的是我有幾個文件(txt)每個大約2GB。我需要削減文件讓我們說每當'%% XGF NEW_SET'標記出現我需要創建新文件並將其存儲。我認爲這個標記大概每40-50行出現一次。每行有4-20個字符。 所以我需要將大文件切割成數千個小文件,然後再處理它們。我想到了這樣的示例代碼。高效的方式來讀取和剪切文件

 DirectoryInfo di = new DirectoryInfo(ConfigurationManager.AppSettings["BilixFilesDir"]); 
     var files = di.GetFiles(); 
     int count = 0; 
     bool hasObject = false; 
     StringBuilder sb = new StringBuilder(); 
     string line = ""; 
     foreach (var file in files) 
     { 
      using (StreamReader sr = new StreamReader(file.FullName,Encoding.GetEncoding(1250))) 
      { 
       while ((line = sr.ReadLine()) != null) 
       { 
        //when new file starts 
        if (line.Contains("%%XGF NEW_SET")) 
        { 
         //when new file existed I need to store old one 
         if (hasObject) 
         { 
          File.WriteAllText(string.Format("{0}/{1}-{2}", ConfigurationManager.AppSettings["OutputFilesDir"], count++, file.Name), sb.ToString()); 
          sb.Length = 0; 
          sb.Capacity = 0; 

         } 
         //setting exist flag 
         hasObject = true; 
        } 
        //when there is no new object 
        else 
         //when object exists adding new lines 
         if (hasObject) 
          sb.AppendLine(line); 
       } 
       //when all work done saving last object 
       if (hasObject) 
       { 
        File.WriteAllText(string.Format("{0}/{1}-{2}", ConfigurationManager.AppSettings["OutputFilesDir"], count++, file.Name), sb.ToString()); 
        sb.Length = 0; 
        sb.Capacity = 0; 
       } 
      } 
     } 
    } 

所以我的例子看起來像那樣,但我需要高效率。任何想法我可以改進我的解決方案?由於

+0

'%% XGF NEW_SET`是分割線上唯一的東西嗎?如果沒有,你正在失去其他信息,因爲你正在扔掉這條線。 – 2011-02-11 14:47:58

回答

2

什麼效率,你需要的排序,以你目前的代碼會比較?個人而言,我可能會略微不同 - 讓讀者和作家隨時打開,並寫下你讀的每一行,除非它是「剪切」行,在這種情況下,你只需關閉現有的作者並開始一個新的。儘管如此,我不會特別期待效率的不同。

1

我會完全消除對StringBuilder的需要,通過創建到被寫入直到下一個對象來輸出文件流。然後切換到新對象上的新文件流。

0

感謝您的所有提示。同時再考慮之後,我已經修改了我的代碼爲sommething這樣的:

DirectoryInfo di = new DirectoryInfo(ConfigurationManager.AppSettings["BilixFilesDir"]); 
//getting all files from dir 
var files = di.GetFiles(); 
int count = 0; 
bool hasObject = false; 
string line = ""; 
StreamWriter sw = null; 
foreach (var file in files) 
{ 
    using (StreamReader sr = new StreamReader(file.FullName, Encoding.GetEncoding(1250))) 
    { 
     while ((line = sr.ReadLine()) != null) 
     { 
      //when new file starts 
      if (line.Contains("%%XGF NEW_SET")) 
      { 
       //when new file existed I need to store old one 
       if (hasObject) 
       { 
        sw.Close(); 
       } 
       else 
       { 
        //creating new file and setting exist flag 
        hasObject = true; 
        sw = new StreamWriter(string.Format("{0}/{1}-{2}", ConfigurationManager.AppSettings["OutputFilesDir"], count++, file.Name)); 
        //Bill bill = new Bill();        
       } 
      } 
      else 
       //when object exists adding new lines 
       if (hasObject) 
        sw.WriteLine(line); 
     } 
     //when all work done saving last object 
     if (hasObject) 
     { 
      sw.Close(); 
      hasObject = false; 
     } 
    } 
} 
sw.Dispose(); 

你怎麼看待sommething這樣呢?

還有一兩件事,我需要做: 我的大文件可以存儲不同的文檔。他們都有不同的開始標誌。 假設有20種文件。有時會有相同的標記開始,但在文檔內部有一些額外的標記可以讓我識別文檔的類型。我的意思是,例如2個文件具有相同的標記開始像「%% XGF NEW_SET」但是你對後者像標記「BILL_A」和其他沒有。而且我必須爲每個剪切文件創建一個文件,其中包含文檔中的一些索引以及包含該類型的字符串。所以在保存我的StreamWriter之前,我必須提取所有這些索引以及我對StringBuilder思考的文檔類型。所以當我需要這種高效率時,這是下一個地方。任何好的提示?

0

有許多不同的方法來讀取和.NET寫出來的文件。我寫了一個基準測試程序,並給予在我的博客的結果:

http://designingefficientsoftware.wordpress.com/2011/03/03/efficient-file-io-from-csharp

我建議使用Windows的ReadFile和WriteFile方法,如果你需要的性能。避免使用任何異步方法,因爲我的基準測試結果表明,使用同步I/O方法可以獲得更好的性能 - 至少對於FileStream來說,它是用於讀取文件的最快.NET類。我在C#中編寫了一個類,它封裝了ReadFile和WriteFile功能使其非常易於使用。

另一個有趣的結果是,它看着東西就像讀線.VS。以每個65,536字節的塊讀取數據並將其解析爲行。事實證明,讀取塊中的數據,然後將其解析爲程序內部的行更加高效。我的下載有一些如何做到這一點的例子。

我很喜歡它,如果你要下載它並試用它並在這裏報告或者在我的博客上發表評論,如果它比StreamReader更快。根據我有限的基準,它顯着更快。

提高程序性能的另一個想法是創建多個線程並讓每個線程處理一個文件。既然你說過你有幾個大文件,我會分解它,這樣每個大文件都有一個單獨的線程。

如果你使用字符串做了很多工作,那麼你一定要使用StringBuilder。但是,也許更有效的方法是將數據讀入一個字節數組,然後爲輸出構建一個字節數組。如果這不比使用StringBuilder更有效,我會感到驚訝。

Bob Bryan MCSD

相關問題