Guido Van Rossum 在这个 article 中展示了 Python 的简单性并利用此函数缓冲读取未知长度的文件:
def intsfromfile(f):
while True:
a = array.array('i')
a.fromstring(f.read(4000))
if not a:
break
for x in a:
yield x
出于速度原因,我需要在 C++ 中做同样的事情!我有许多文件包含我需要合并的无符号 64 位整数的排序列表。我找到了这件漂亮的 code用于合并 vector 。
我被困在如何为未知长度的文件制作一个 ifstream 将自己呈现为一个 vector ,它可以愉快地迭代直到文件末尾到达。有什么建议么?我是否使用 istreambuf_iterator 建立了正确的树?
最佳答案
为了伪装 ifstream
(或者实际上,任何输入流)以类似于迭代器的形式,你想使用 istream_iterator
或 istreambuf_iterator
模板类。前者对于格式很重要的文件很有用。例如,一个充满空白分隔整数的文件可以读入 vector 的迭代器范围构造函数,如下所示:
#include <fstream>
#include <vector>
#include <iterator> // needed for istream_iterator
using namespace std;
int main(int argc, char** argv)
{
ifstream infile("my-file.txt");
// It isn't customary to declare these as standalone variables,
// but see below for why it's necessary when working with
// initializing containers.
istream_iterator<int> infile_begin(infile);
istream_iterator<int> infile_end;
vector<int> my_ints(infile_begin, infile_end);
// You can also do stuff with the istream_iterator objects directly:
// Careful! If you run this program as is, this won't work because we
// used up the input stream already with the vector.
int total = 0;
while (infile_begin != infile_end) {
total += *infile_begin;
++infile_begin;
}
return 0;
}
istreambuf_iterator
用于一次读取一个字符的文件,而不考虑输入的格式。也就是说,它将返回所有字符,包括空格、换行符等。根据您的应用,这可能更合适。
注意:Scott Meyers 在 Effective STL 中解释了为什么 istream_iterator
的单独变量声明以上是需要的。通常,你会做这样的事情:
ifstream infile("my-file.txt");
vector<int> my_ints(istream_iterator<int>(infile), istream_iterator<int>());
但是,C++ 实际上以一种非常奇怪的方式解析第二行。它将其视为名为 my_ints
的函数的声明它接受两个参数并返回一个 vector<int>
.第一个参数的类型是 istream_iterator<int>
并命名为infile
(括号被忽略)。第二个参数是一个没有名称的函数指针,它采用零参数(因为括号)并返回类型为 istream_iterator<int>
的对象。 .
很酷,但如果你不注意的话也会很恼火。
编辑
这是一个使用 istreambuf_iterator
的例子读取端到端排列的 64 位数字文件:
#include <fstream>
#include <vector>
#include <algorithm>
#include <iterator>
using namespace std;
int main(int argc, char** argv)
{
ifstream input("my-file.txt");
istreambuf_iterator<char> input_begin(input);
istreambuf_iterator<char> input_end;
// Fill a char vector with input file's contents:
vector<char> char_input(input_begin, input_end);
input.close();
// Convert it to an array of unsigned long with a cast:
unsigned long* converted = reinterpret_cast<unsigned long*>(&char_input[0]);
size_t num_long_elements = char_input.size() * sizeof(char) / sizeof(unsigned long);
// Put that information into a vector:
vector<unsigned long> long_input(converted, converted + num_long_elements);
return 0;
}
现在,我个人比较不喜欢这个解决方案(使用 reinterpret_cast
,公开 char_input
的数组),但我对 istreambuf_iterator
还不够熟悉舒适地使用一个超过 64 位的模板化字符,这将使这变得容易得多。
关于c++ - 等效于 C++ 中用于缓冲读取的 python 生成器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4685862/