【问题标题】:C++: How to read large txt file and save to array fasterC++:如何更快地读取大文本文件并保存到数组
【发布时间】:2014-06-30 21:30:27
【问题描述】:

我想读取一个超过 50000 行的大 txt 文件。

文件样本:

John 12 1 956 02 818 912 322 43 161 9 002 768 23 79 9 1 115 7 2 18 59 58 989 3 56 82 59 147 86 62 06 10 538 36 694 952 71 0 2 5 67 103 6 295 933 428 9 70 708 6 73 449 57 283 6 48 139 5 140 34 5 9 95 74 892 9 387 172 44 05 67 534 7 79 5 565 417 252 480 22 503 089 76 433 93 36 374 97 035 70 2 896 0 3 0 259 93 92 47 860

说明: 上面的示例是 txt 文件中的每一行。每个字符和字符串都用空格分隔。

目标: 我想在第一个单词(在本例中:John)之后保存整数的值并保存到行 = txt 文件中的行数 和列 = 100 的整数矩阵。

这是我的代码

Mat readInteger(String path_txt_file){  
int row = 1;
int col = 100;
Mat return_mat;

Mat tmp_mat= Mat(row, col, CV_32F);

fstream input(path_txt_file);
for (std::string line; getline(input, line);)
{
    int posMat = -1;
    vector<string> v = split<string>(line, " ");
    for (int i = 1; i < v.size(); i++)
    {   
        posMat = posMat + 1;
        tmp_mat.at<float>(0, posMat) = atoi(v[i].c_str()); //white  
    }
    return_mat.push_back(tmp_mat);
}
tmp_mat.release();
return return_mat;
}

代码说明

  1. 我遵循从 txt 文件中读取数据的经典方式是 逐行阅读
  2. 我创建了两个 Mat,return_mat 和 tmp_mat
  3. 每行每次 tmp_mat 其 row = 1 和 col = 100 用于存储每行整数 然后我们根据空格分割字符串 之后我们将整个 tmp_mat 推入 return_mat。

结果 我得到了我想要的结果; 不幸的是,当文件太大时(我们需要它)。这个过程太慢了。

问题

我们如何改进这个算法。例如处理1000000行的大文件? 我想知道我们是否应该使用多线程?

谢谢

【问题讨论】:

  • 1Mio 乘以该行是 319MB,这取决于程序中的数据类型甚至更多。 ...“太慢”有多慢?一个文本文件的多线程...?嗯...(分配向量每一行等是
  • “多么慢”:两个多小时,仍然从文件中读取。
  • 您考虑过使用二进制文件吗?然后您可以使用单个读取指令读取整个数组,但必须事先知道数组/向量的大小
  • 多线程并不是解决所有性能问题的灵丹妙药。如果磁盘是瓶颈,那么没有线程池会有所帮助。我建议 (a) 使用 profiler,然后 (b) 改善瓶颈。如果没有测试,我怀疑 I/O 操作是最慢的部分,因此某种缓冲(或使用 MMF)可能会带来显着的提升。
  • 这似乎慢得惊人。一个 300mb 的文件不应该花那么长时间来加载和解析。几个更快速的建议:使用正常的cin &gt;&gt; 过程来填充矩阵的每一行,而不是构建字符串,将字符串拆分为向量,转换每个元素然后销毁向量。还要确保return_mat 已预先分配足够的内存来存储整个数据集。最后,您可能会考虑内存映射文件,尽管我不知道它们在这里会有多大用处。

标签: c++ arrays multithreading file-io profiling


【解决方案1】:

我不知道您是否对如何构建原始文件有任何意见,但您可以提出一些更改的建议。 我不认为阅读速度很慢,但所有的演员都是。 您首先拆分缓慢的行,然后首先将其转换为整数,然后再转换为浮点数。您还使用 Mat.at 函数,据我所知,这也不是很快(可能是错误的)。 同样将一行推回另一个垫子与复制需要时间一样。 这不是很多,但随着时间的推移会随着大文件累积。

我的建议如下:

创建一个如下所示的结构:

struct Data
{
    char[100] FirstWord;
    std::array<int, 100> Data;
}

您使用二进制文件并将此结构写入其中,而不是创建文本文件。 (看看写入二进制文件:http://www.cplusplus.com/reference/ostream/ostream/write/

如果您再次读取文件,您可以执行以下操作:

ifstream file ("File.dat", ios::in|ios::binary);
if (file.is_open())
{
    Data D;
    file.read(reinterpet_cast<char*>(&D), sizeof(D));
    Mat A(RowSize,ColSize,D.data());
}

通过这种方式,您不需要进行所有的转换。你只需要一份。

希望对你有帮助

【讨论】:

    猜你喜欢
    • 2015-08-07
    • 2013-11-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多