2011-12-10 31 views
1

我想把一個大的電信賬單分成CSV文件,根據賬單中的電話號碼將300MB分成更小的塊。在c#中分割CSV文件的有效方法

某些電話號碼有20行的帳單,有些擁有超過1000行的電話號碼,所以它是動態的。在第一階段,我閱讀帳單並使用LINQ按電話號碼對它們進行分組,並計算CSV文件中針對每個電話號碼帳單的帳單包含的行數。然後插入一個List:split_id,起始行,結束行。 (起始行從0開始)。

下面的腳本是我用來分割小額賬單的。但是,即使每個文件下降到100KB以下,這300MB的電話號碼也會異常超過7500個,因此需要永久處理分割賬單。

static void FileSplitWriter(List<SplitFile> pList, string info) 
    { 

     pList.ForEach(delegate(SplitFile per) 
     { 
      int startingLine = per.startingLine; 
      int endingLine = per.endingLine; 
      string[] fileContents = File.ReadAllLines(info); 
      var query = fileContents.Skip(startingLine - 1).Take(endingLine - (startingLine - 1)); 
      string directoryPath = Path.GetDirectoryName(info); 
      string filenameok = Path.GetFileNameWithoutExtension(info); 

      StreamWriter ffs = new StreamWriter(directoryPath + "\\" + filenameok + "_split" + per.id + ".csv"); 
      foreach (string line in query) 
      { 
       ffs.WriteLine(line); 
      } 
      ffs.Dispose(); 
      ffs.Close(); 
     }); 


    } 

我的問題是,是否有可能讓這個過程更快/更有效率?以目前的速度,它將需要3個小時左右才能分割文件。

+2

而不是'ffs.Dispose()'爲什麼不使用'using'語句? – spender

+0

什麼是信息? – dasblinkenlight

+3

你爲什麼要將完整的文件讀入循環內存中? – Magnus

回答

2

嘗試將文件的讀取移動到外循環:

static void FileSplitWriter(List<SplitFile> pList, string info) { 
    string[] fileContents = File.ReadAllLines(info); 
    string directoryPath = Path.GetDirectoryName(info); 
    string filenameok = Path.GetFileNameWithoutExtension(info); 
    pList.ForEach(delegate(SplitFile per) { 
     int startingLine = per.startingLine; 
     int endingLine = per.endingLine; 
     var query = fileContents.Skip(startingLine - 1).Take(endingLine - (startingLine - 1)); 
     StreamWriter ffs = new StreamWriter(directoryPath + "\\" + filenameok + "_split" + per.id + ".csv"); 
     foreach (string line in query) { 
      ffs.WriteLine(line); 
     } 
     ffs.Close(); 
     ffs.Dispose(); 
    }); 
} 
+1

也許你應該在調用Dispose之前調用'Close'(關於'ffs')。 –

+0

@RonKlein非常棒!非常感謝你! – dasblinkenlight

2

我建議你使用存在的許多快速CSV解析庫之一。

還有several發表在代碼項目和其他地方,以及filehelpers

3

它看起來像這樣的代碼的最沒有效率的部分是,你正在閱讀的整個300MB的文件到內存多個倍。您應該只需要讀一次...

  1. 將文件讀入一些枚舉數據結構。
  2. 按電話號碼分組。
  3. 循環遍歷每個組,並將每個組寫入文件。

注:如果您使用.NET 4.0,您可能會獲得通過使用File.ReadLines()(而不是ReadAllLines)一些內存效率。