加速从c++文件中读取整数
Speed up integer reading from file in C++
我正在逐行读取一个文件,并从中提取整数。注意事项:
- 输入文件不是二进制文件;
- 我无法在内存中加载整个文件;
-
文件格式(只有整数,用一些分隔符分隔):
x1 x2 x3 x4 ... y1 y2 y3 ... z1 z2 z3 z4 z5 ... ...
只是为了添加上下文,我正在读取整数,并使用std::unordered_map<unsigned int, unsinged int>
对它们进行计数。
简单地遍历行,并分配无用的stringstream,如下所示:
std::fstream infile(<inpath>, std::ios::in);
while (std::getline(infile, line)) {
std::stringstream ss(line);
}
700MB的文件需要2.7s。
解析每行:
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。
还有什么比这些方法更快的吗?我认为没有必要加快文件读取的速度,只需要加快解析本身——尽管两者都不会造成伤害(:
程序
#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 formatn";
}
}
} while (std::cin);
}
需要1.25秒来处理相同的文件。
流速度很慢。如果你真的想要快速地做一些事情,将整个文件加载到内存中,并在内存中解析它。如果你真的不能把它全部加载到内存中,那就把它加载成块,让这些块尽可能的大,然后在内存中解析这些块。
在内存中解析时,将空格和行尾替换为空,以便您可以使用atoi
转换为整数。
哦,你会在数据块的结尾遇到问题,因为你不知道数据块的结尾是否切断了一个数字。为了轻松解决这个问题,在块结束之前停止一小段距离(16字节应该可以),并在加载它之后的下一个块之前将这个尾部复制到开始。
您尝试过输入迭代器吗?
它跳过字符串的创建:
std::istream_iterator<int> begin(infile);
std::istream_iterator<int> end;
int item = 0;
while(begin != end)
item = *begin++;
为什么不跳过流和行缓冲区,直接从文件流中读取呢?
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;
}
http://ideone.com/FNJKFa 遵循Jack Aidley的回答(不能在评论中添加代码),这里有一些伪代码:
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
}
相关文章:
- 如何在c++中从文本文件中逐行读取整数
- Arduino从Txt读取整数
- 从二进制文件中读取整数数组
- 使用字符串流读取整数并将它们相加
- 如何在从文件中读取整数时使用 file.eof()?
- C++从键盘读取整数的功能
- 为什么字符串流只读取整数中的第一个数字?如何使它只在空白处移动?
- 如何从文本文件C++读取整数和特殊字符
- C++ 从控制台读取整数数组
- 从文本文件中读取整数并将它们存储到数组中
- 输入重定向读取整数和char C
- 从文件读取整数到矩阵 (c++)
- 如何读取整数直到线结束
- 从输入文件读取整数,仅存储数组C 中的唯一整数
- 从文本文件中读取整数
- 读取整数对,直到文本输入文件中的换行符
- 在C++中从文件中读取整数和字符
- 使用 MFC C++ 6.0 从 ms 访问中读取整数数据
- 从标准输入和输入值中读取整数到向量
- 从文件中读取整数到数组