29.需要依次录入字符时考虑使用istreambuf_iterator

问题实例

 
假设我们需要拷贝一个文本文件到一个字符串:

1
2
3
4
//该程序仅作示例,实际编译效果与设想不符,原因见Effective STL 6)
ifstream inputFile("interestingData.txt");
string fileData((istream_iterator<char>(inputFile)),
istream_iterator<char>());

实际上这并没有完全copy文本,因为istream_iterator使用operator>>,该操作符在默认情况下忽略空格。
如果你不想所有空格都莫名消失,那你应该覆盖默认情况:
1
2
3
ifstream inputFile("interestingData.txt");
inputFile.unset(ios::skipws); // 关闭inputFile的忽略空格标志
string fileData((istream_iterator<char>(inputFile)), istream_iterator<char>());

然而你会发现这种拷贝速度很慢,因为operator>>采取格式化输入,它需要建立sentry对象(为每个operator>>调用进行建立和清除活动的特殊的iostream对象),必须检查流标志位,以及是否需要抛出异常等等操作,这些操固然很重要,但当我们需要的只是从输入流中抓取下一个字符时,这一切都是不必要的。


解决方案

 
istreambuf_iterator的特性是直接进入输入流缓冲区读取字符,使用方法如下:

1
2
3
4
//再次重申这个没法正常运行,只是示例
ifstream inputFile("interestingData.txt");
string fileData((istreambuf_iterator<char>(inputFile)),
istreambuf_iterator<char>());

istreambuf_iterator也无需考虑空格的因素,因为空格不会被输入流摒弃。
同样的,逐个输出字符时也应该使用ostreambuf_iterator.