我正在逐行读取文件,并从中提取整数。一些值得注意的要点:
文件格式(仅限整数,以某些分隔符分隔):
x1 x2 x3 x4 ...
y1 y2 y3 ...
z1 z2 z3 z4 z5 ...
...
只是添加上下文,我正在使用std::unordered_map<unsigned int, unsinged int>
读取整数并计算它们。
简单地循环遍历行,并分配无用的字符串流,如下所示:
std::fstream infile(<inpath>, std::ios::in);
while (std::getline(infile, line)) {
std::stringstream ss(line);
}
给了我~7.7s的700MB文件。
解析每一行:
unsigned int item;
std::fstream infile(<inpath>, std::ios::in);
while (std::getline(infile, line)) {
std::stringstream ss(line);
while (ss >> item);
}
给同一个文件~17.8秒。
如果我将操作符更改为std::getline
+ atoi
:
unsigned int item;
std::fstream infile(<inpath>, std::ios::in);
while (std::getline(infile, line)) {
std::stringstream ss(line);
while (std::getline(ss, token, ' ')) item = atoi(token.c_str());
}
它给出~14.6s。
有没有比这些方法更快的东西?我不认为有必要加快文件阅读速度,只需要解析文件本身 - 但这两种情况都不会造成伤害(:
答案 0 :(得分:9)
这个程序
#include <iostream>
int main ()
{
int num;
while (std::cin >> num) ;
}
需要大约17秒才能读取文件。这段代码
#include <iostream>
int main()
{
int lc = 0;
int item = 0;
char buf[2048];
do
{
std::cin.read(buf, sizeof(buf));
int k = std::cin.gcount();
for (int i = 0; i < k; ++i)
{
switch (buf[i])
{
case '\r':
break;
case '\n':
item = 0; lc++;
break;
case ' ':
item = 0;
break;
case '0': case '1': case '2': case '3':
case '4': case '5': case '6': case '7':
case '8': case '9':
item = 10*item + buf[i] - '0';
break;
default:
std::cerr << "Bad format\n";
}
}
} while (std::cin);
}
对于同一个文件需要1.25秒。做你想要的......
答案 1 :(得分:2)
流很慢。如果你真的想做的事情,请将整个文件快速加载到内存中,并在内存中解析它。如果你真的无法将它全部加载到内存中,请将它们加载到块中,使这些块尽可能大,并将块解析到内存中。
在内存中解析时,用空值替换空格和行结尾,这样就可以使用atoi
转换为整数。
哦,你会遇到块结束的问题,因为你不知道块末端是否会切断一个数字。为了解决这个问题,可以在块结束之前轻松地停止一小段距离(16字节应该这样做)并将此尾部复制到开始,然后再加载它之后的下一个块。
答案 2 :(得分:1)
您是否尝试过输入迭代器?
它会跳过字符串的创建:
std::istream_iterator<int> begin(infile);
std::istream_iterator<int> end;
int item = 0;
while(begin != end)
item = *begin++;
答案 3 :(得分:1)
为什么不直接跳过流和行缓冲区并直接读取文件流?
template<class T, class CharT, class CharTraits>
std::vector<T> read(std::basic_istream<CharT, CharTraits> &in) {
std::vector<T> ret;
while(in.good()) {
T x;
in >> x;
if(in.good()) ret.push_back(x);
}
return ret;
}
答案 4 :(得分:1)
vector<char> buff( chunk_size );
roffset = 0;
char* chunk = &buff[0];
while( not done with file )
{
fread( chunk + roffset, ... ); // Read a sizable chunk into memory, filling in after roffset
roffset = find_last_eol(chunk); // find where the last full line ends
parse_in_mem( chunk, chunk_size - roffset ); // process up to the last full line
move_unprocessed_to_front( chunk, roffset ); // don't re-read what's already in mem
}