为了将ifstream(或实际上是任何输入流)伪装成类似于迭代器的形式,您需要使用istream_iterator 或istreambuf_iterator 模板类。前者对于需要考虑格式的文件很有用。例如,一个充满以空格分隔的整数的文件可以读入向量的迭代器范围构造函数,如下所示:
#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 位字符,这将让这更容易。