2010-06-24 47 views
2

我通常使用csv parser中描述的方法來讀取電子表格文件。但是,當讀取大約40列和250K行數據的64MB文件時,大約需要4分鐘。在原始方法中,使用CSVRow類逐行讀取文件,並使用專用向量將所有數據存儲在一行中。有效地讀取C++中的大型電子表格文件

有幾件事情需要注意:

  • 我做的矢量的儲備足夠的容量,但沒有太大的幫助。
  • 我還需要在讀取每行時創建某個類的實例,但即使代碼剛剛在數據中讀取而未創建任何實例,也需要很長時間。
  • 該文件以製表符分隔而不是逗號分隔,但我認爲它不重要。

由於在該文件中的某些列是不可用的數據,我改變該方法以具有私人字符串構件來存儲所有的數據,然後找到第(n-1)個的位置和第n個分隔符獲取有用的數據(當然還有許多有用的列)。通過這樣做,我避免了一些push_back操作,並將時間縮短了2分多鐘。但是,這對我來說似乎還太長。

這裏是我的問題:

  1. 有沒有辦法更有效地讀出這樣的 電子表格文件?

  2. 我應該通過緩衝區 而不是逐行讀取文件嗎?如果是這樣,如何通過緩衝區讀取 並使用csvrow 類?

  3. 我還沒試過提升標記化器,是 那效率更高?

謝謝你的幫忙!

+1

沉重的堆流失。閱讀:http://blogs.msdn.com/b/ricom/archive/2005/05/10/performance-quiz-6-chinese-english-dictionary-reader.aspx?wa=wsignin1.0 – 2010-06-24 14:53:23

回答

2

它看起來像你被IO瓶頸。不要逐行讀取文件,而應以8 MB爲單位讀取它。解析讀取記錄的塊並確定塊的結尾是否是部分記錄。如果是,請複製塊中最後一條記錄的部分並將其前置到下一個塊。重複,直到文件全部被讀取。這樣,對於一個64 MB的文件,你只需要8個IO請求。您可以嘗試使用塊大小來確定什麼能夠提供最佳的性能與內存使用率。

0

如果讀取整個數據到存儲器上可接受的(顯然是),那麼我這樣做:

  1. 讀取整個文件到一個std ::矢量
  2. 填充的載體>其中包含所有換行字符和單元格數據的起始位置。這些位置表示每個單元

一些代碼草圖的開始/結束驗證這個想法:

vector<vector<vector<char>::size_Type> > rows; 
for (vector<char>::size_type i = 0; i < data.size(); ++i) { 
    vector<vector<char>::size_type> currentRow; 
    currentRow.push_back(i); 
    while (data[i] != '\n') { 
     if (data[i] == ',') { // XXX consider comma at end of line 
      currentRow.push_back(i); 
     } 
    } 
    rows.push_back(currentRow); 
} 
// XXX consider files which don't end in a newline 

因此,你知道所有的換行和所有逗號的位置,你有完整的CSV日期可用作一個連續的內存塊。所以,你可以很容易地提取這樣的單元格文本:

// XXX error checking omitted for simplicity 
string getCellText(int row, int col) 
{ 
    // XXX Needs handling for last cell of a line 
    const vector<char>::size_type start = rows[row][col]; 
    const vector<char>::size_type end = rows[row][col + 1]; 
    return string(data[start], data[end]); 
} 
0

This article應該是有幫助的。

簡而言之:
1.使用內存映射文件或讀取4kbyte塊中的文件來訪問數據。內存映射文件將會更快。
2.儘量避免在解析循環中使用push_back,std :: string操作(如+)和來自stl的類似例程。它們很好,但它們都使用動態分配的內存,動態內存分配速度很慢。任何經常動態分配的東西都會讓你的程序變慢。嘗試在解析之前預先分配所有緩衝區。計算所有令牌以便爲它們預分配內存應該不困難。
3.使用分析器來確定導致放緩的原因。
4.您可能想嘗試避免使用iostream的< <和>>操作符,並自己解析文件。

通常,高效的C/C++解析器實現應該能夠在3秒內解析20兆字節的大文本文件。