2010-06-01 44 views
1

我有幾個文件的內容需要合併到一個文件中。我有下面的代碼可以做到這一點......但從內存使用情況來看,它似乎相當低效......你會建議一個更好的方法來做到這一點嗎?內存高效的文件追加

的Util.MoveFile功能只是佔整個卷

private void Compose(string[] files) 
    { 
     string inFile = ""; 
     string outFile = "c:\final.txt"; 

     using (FileStream fsOut = new FileStream(outFile + ".tmp", FileMode.Create)) 
     { 
      foreach (string inFile in files) 
      { 
       if (!File.Exists(inFile)) 
       { 
        continue; 
       } 

       byte[] bytes; 
       using (FileStream fsIn = new FileStream(inFile, FileMode.Open)) 
       { 
        bytes = new byte[fsIn.Length]; 
        fsIn.Read(bytes, 0, bytes.Length); 
       } 

       //using (StreamReader sr = new StreamReader(inFile)) 
       //{ 
       // text = sr.ReadToEnd(); 
       //} 

       // write the segment to final file 
       fsOut.Write(bytes, 0, bytes.Length); 

       File.Delete(inFile); 
      } 
     } 

     Util.MoveFile(outFile + ".tmp", outFile); 

}

+0

也許看到:在C#中連接三個文件的最快方法是什麼? http://stackoverflow.com/questions/444309/what-would-be-the-fastest-way-to-concatenate-ree-files-in-c – 2010-06-01 02:57:36

+0

你爲什麼覺得效率低下? – 2010-06-01 02:57:42

+0

如果這些是文本文件,爲什麼不使用「貓?」 http://en.wikipedia.org/wiki/Cat_%28Unix%29 – Alan 2010-06-01 02:57:48

回答

0

你可以用較小的固定大小的緩衝區,像這樣:

byte[] bytes = new byte[8192]; // adjust this as needed 
int bytesRead; 
do { 
    bytesRead = fsIn.Read(bytes, 0, bytes.Length); 
    fsOut.Write(bytes, 0, bytesRead); 
} while (bytesRead > 0); 

這是相當自我解釋除了在最後一個塊,所以基本上發生了什麼是我傳遞一個8K字節數組到Read方法返回它實際讀取的字節數。所以在Write調用中,我傳遞的值介於0和8192之間。換句話說,在最後一個塊上,即使我傳遞了一個8192字節的字節數組,bytesRead可能只有10個,在這種情況下,只有前10個字節需要寫入。

編輯

我編輯我的答案稍有不同的方式來做到這一點。不是使用輸入文件的位置來確定何時跳出循環,而是檢查bytesRead是否大於零。此方法適用於任何類型的流來複制流,包括沒有固定或已知長度的流。

+0

感謝Josh ...我將執行此操作並描述結果 – lboregard 2010-06-01 03:16:03

+0

請注意,就像任何事情一樣,性能和內存使用之間總是存在折衷。最快的方法就是你最初展示它的方式......根據需要使用盡可能多的內存。另請注意,除非使用特定的構造函數,否則由.NET完成的默認緩衝仍將發生。文件系統仍然會應用自己的寫緩衝。但至少這可以讓你處理大文件而不用擔心OutOfMemoryException。 – Josh 2010-06-01 03:22:16

+0

我會使用更大的緩衝區,比如1​​Mb的典型磁盤。計算緩衝區大小的信封方式的後面,您需要有效地將磁盤用於非SSD磁盤:將磁盤搜索時間乘以吞吐量。對於現代磁盤,您會得到(〜10ms)*(〜100Mb/sec)= 1MB。 8KB可能會顯着減慢你的速度。 – Michael 2010-06-01 04:40:12

1

有時它只是更好地調用shell函數,而不是重新實現功能的移動文件。正如艾倫說,你可以使用CAT在UNIX系統上或者是在Windows中可以使用內置的命令處理器

copy file1+file2+file3 concated_file 
+0

感謝preet sangha ...你是對的...在創建新的shell進程/線程時有一個開銷,但最終它應該比任何我可能做的更有效率..我會嘗試實現和配置 – lboregard 2010-06-01 03:17:16

+0

重要的是你最後說的 - 簡介! – 2010-06-01 03:28:17