2012-12-06 162 views
12

的第一行我有我導入到數據庫中許多大的CSV文件(每個1-10 GB)。對於每個文件,我需要替換第一行,以便可以將標題格式化爲列名稱。我目前的解決方案是:快速更換大文件

using (var reader = new StreamReader(file)) 
{ 
    using (var writer = new StreamWriter(fixed)) 
    { 
     var line = reader.ReadLine(); 
     var fixedLine = parseHeaders(line); 
     writer.WriteLine(fixedLine); 

     while ((line = reader.ReadLine()) != null) 
      writer.WriteLine(line); 
    } 
} 

什麼是更快的方式來只替換第1行而無需遍歷這些巨大的文件的每一行?

+0

我可能只是從命令行執行此操作。 'copy headerfile + csvfile newfile'你可以創建一個包含所有需要修改的文件的批處理文件。 (哦,除了看起來你不知道標題是什麼,否則這不會起作用) –

+0

如果你正在使用的工具恰好通過'stdin'輸入輸入:而不是文件,您可以創建一個由標題和正文組成的流,並在需要時將其提供到導入工具中。例如'cat headerfile bigfile | import_tool' –

+0

這對fixedLine的長度和第一行非常敏感。 fixedLine可以更大嗎? line2是否可以移動到文件的末尾? –

回答

7

如果您可以保證fixedLineline的長度相同(或更少),您可以在原地更新文件而不是複製它們。

如果沒有,你都不可能通過訪問StreamReaderStreamWriter.BaseStream,做塊大副本(使用,比如說,一個32K字節的緩衝區)做複製得到一個小的性能提升,這將至少消除花在檢查每個角色上的時間,看看它是否是現在的reader.ReadLine()現在發生的行尾字符。

+0

如果少了,你會如何處理「免費」空間?用空格填充它? – Jodrell

+0

可能,但它取決於格式。在CSV文件中,我可以引用標題元素,並在逗號後添加填充空格。 – prprcupofcoffee

+1

+1。 @Jodrell,是的,在大多數情況下空格被忽略的CSV - 所以使用它們填充將是好的(我試圖建議它在我的相同答案:))。空間對於大多數編碼也是安全的 - 所以可以根據需要直接寫入流中。 –

6

唯一能夠顯着提高速度的是如果你真的可以用代替第一行。如果新的第一行不再比舊的第一行更小 - 請仔細地用第一行替換(如果需要,填充空格)。

否則 - 你必須創建新的文件,第一行後,其餘的複製。您可以通過將緩衝區大小/顯式副本調整爲二進制/每個分配的大小來優化複製,但這不會改變您需要複製整個文件的事實。

如果您打算將CSV數據放入數據庫,還有一種作弊方式:如果順序無關緊要,您可以從頭開始讀取一些行,將其替換爲新的標題並將刪除的行添加到文件的末尾。

邊注:如果這是一次性操作我會簡單地複製文件,並用它做...調試將數據插入文本文件中他們有不同的編碼可能不值得努力代碼。