2010-06-24 49 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兆字节的大文本文件。