【问题标题】:The fastest way to read csv file in c++ which contains large no of columns and rows在 C++ 中读取包含大量列和行的 csv 文件的最快方法
【发布时间】:2019-11-26 01:58:40
【问题描述】:

我有一个超过 13 列的以竖线分隔的数据文件。总文件大小超过 100 MB。我正在阅读每一行,将字符串拆分为std::vector<std::string>,以便进行计算。我对文件中的所有行重复此过程,如下所示:

    string filename = "file.dat";
    fstream infile(filename);
    string line;
    while (getline(infile, line)) {
        string item;
        stringstream ss(line);
        vector<string> splittedString;
        while (getline(ss, item, '|')) {
            splittedString.push_back(item);
        }
        int a = stoi(splittedString[0]); 
        // I do some processing like this before some manipulation and calculations with the data
    }

然而,这非常耗时,而且我很确定这不是读取 CSV 类型文件的最优化方式。如何改进?

更新

我尝试使用 boost::split 函数而不是 while 循环,但它实际上更慢。

【问题讨论】:

  • 您总是可以使用专门用于读取 CSV 的库
  • 对于开始将 std::vector 声明移出 while 循环并改为在循环内清除。或者,如果列数始终相同,您可以使用std::array(也在循环外声明)。就像已经建议的那样,使用 csv 库是最好的选择。为什么要重新发明轮子?
  • 这里的“非常耗时”是什么意思?您需要达到的性能是什么?行是否独立,以便可以并行进行处理?
  • 我想不出更好的方法,我个人会和你的编码一样。
  • CSV 读取起来非常简单,以至于读取它仅受媒体速度的限制,即使是最快的 SSD。因此,您的问题可能在于在紧密循环中创建动态对象,以及类似的其他处理,并且这一切都在调试构建中进行测量。

标签: c++ string performance optimization vector


【解决方案1】:

您没有 CSV 文件,因为 CSV 代表逗号分隔值,而您没有。
您有一个分隔的文本文件(显然由 "|" 分隔)。解析 CSV 比在 "," 上简单地拆分更复杂。

无论如何,如果您的方法没有太大的变化,这里有一些建议:

  • 使用(更多)缓冲
  • vector 移出循环并在每次迭代中将clear() 移出。这将节省堆重新分配。
  • 使用string::find() 而不是stringstream 来拆分字符串。

这样的……

using namespace std;
int main() {
    string filename = "file.dat";
    fstream infile(filename);
    char buffer[65536];
    infile.rdbuf()->pubsetbuf(buffer, sizeof(buffer));
    string line;
    vector<string> splittedString;
    while (getline(infile, line)) {
        splittedString.clear();
        size_t last = 0, pos = 0;
        while ((pos = line.find('|', last)) != std::string::npos) {
            splittedString.emplace_back(line, last, pos - last);
            last = pos + 1;
        }
        if (last)
            splittedString.emplace_back(line, last);
        int a = stoi(splittedString[0]);
        // I do some processing like this before some manipulation and calculations with the data
    }
}

【讨论】:

  • 这实际上减少了 63% 的处理时间。谢谢
【解决方案2】:

您可以通过消除“vector splittedString;”再节省 50%并使用 strtok_s() 就地解析

int main() {
auto t1 = high_resolution_clock::now();
long long a(0);

string filename = "file.txt";
fstream infile(filename);
char buffer[65536];
infile.rdbuf()->pubsetbuf(buffer, sizeof(buffer));
string line;
while (getline(infile, line)) {

    char * pch = const_cast<char*>(line.data());
    char *nextToken = NULL;
    pch = strtok_s(pch, "|", &nextToken);
    while (pch != NULL)
    {
        a += std::stoi(pch);
        pch = strtok_s(NULL, "|", &nextToken);
    }
}

auto t2 = high_resolution_clock::now();
auto duration = duration_cast<microseconds>(t2 - t1).count();
std::cout << duration << "\n";
std::cout << a << "\n";

}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-10-26
    • 2019-07-31
    • 2021-10-15
    • 2018-03-11
    • 2015-09-13
    • 1970-01-01
    • 2012-10-20
    • 1970-01-01
    相关资源
    最近更新 更多