我通常使用csv parser中描述的方法来阅读电子表格文件。但是,当读取具有大约40列和250K行数据的64MB文件时,大约需要4分钟。在原始方法中,CSVRow类用于逐行读取文件,私有向量用于存储行中的所有数据。
有几点需要注意:
由于该文件中的某些列不是有用的数据,因此我将方法更改为具有私有字符串成员来存储所有数据,然后找到第(n-1)个和第n个分隔符的位置以获得有用的数据数据(当然有很多有用的专栏)。通过这样做,我避免了一些push_back操作,并将时间缩短到2分多钟。但是,这对我来说似乎太长了。
以下是我的问题:
有没有办法阅读这样的 电子表格文件更有效率?
我应该通过缓冲区读取文件 而不是逐行?如果是这样,怎么样 通过缓冲区读取并使用csvrow 类
感谢您的帮助!
答案 0 :(得分:2)
看起来你被IO瓶颈了。不是逐行读取文件,而是以8 MB的块读取它。解析块读取的记录,并确定块的结尾是否是部分记录。如果是,则从块中复制最后一条记录的部分并将其添加到下一个块。重复,直到文件全部被读取。这样,对于64 MB文件,您只需要发出8个IO请求。您可以尝试使用块大小来确定与内存使用情况相比最佳性能。
答案 1 :(得分:0)
如果将整个数据读入可接受的内存(显然是这样),那么我会这样做:
一些代码草图来展示这个想法:
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]);
}
答案 2 :(得分:0)
This article应该会有所帮助。
简而言之:
1.使用内存映射文件或以4kbyte块读取文件以访问数据。内存映射文件会更快
2.尽量避免在解析循环中使用push_back,std :: string操作(如+)和类似的stl例程。它们很好,但它们都使用动态分配的内存,动态内存分配很慢。任何经常动态分配的东西都会使你的程序变慢。尝试在解析之前预先分配所有缓冲区。计算所有令牌以便为它们预分配记忆应该不难
3.使用分析器确定导致减速的原因
4.您可能希望尽量避免使用iostream的&lt;&lt;和&gt;&gt;运算符,并自己解析文件。
通常,高效的C / C ++解析器实现应该能够在3秒内解析20兆字节的大文本文件。