使用 istreambuf_iterator 读取文件内容,赋值给 std::string
需要一个一个字符输入时考虑使用istreambuf_iterator
假设我们要把一个文本文件拷贝到一个字符串对象中。似乎可以用一种很有道理的方法完成:
ifstream inputFile("d:\\test.plist");
string fileData((istream_iterator<char>(inputFile)), istream_iterator<char>());
//为什么它不是很正确看下文
//关于这个语法的警告,参见条款6
很快你就会发现这种方法无法把文件中的空格拷贝到字符串中。那是因为istream_iterators使用operator<<函数来进行真的读取,而且operator<<函数在默认情况下忽略空格。
假如你想保留空格,你要的做就是覆盖默认情况。只要清除输入流的skipws标志就行了:
ifstream inputFile("d:\\test.plist");
inputFile.unset(ios::skipws); // 关闭inputFile的忽略空格标志
string fileData((istream_iterator<char>(inputFile)), istream_iterator<char>());
现在inputFile中的所有字符都拷贝到fileData中了。
此时,你会发现它们的拷贝速度不像你想象的那么快。
istream_iterators所依靠的operator<<函数进行的是格式化输入,这意味着,每次你调用的时候它们都必须做大量工作。它们必须建立和销毁sentry对象(为每个operator<<调用进行建立和清除活动的特殊的iostream对象),
它们必须检查可能影响它们行为的流标志(比如skipws),它们必须进行全面的读取错误检查,而且如果它们遇到问题,它们必须检查流的异常掩码来决定是否该抛出一个异常。
如果进行格式化输入,这些都是重要的活动,但如果你需要的只是从输入流中抓取下一个字符,这样做就过度了。
一个更高效的方法是使用STL最好的秘密武器之一:istreambuf_iterators。
你可以像istream_iterator一样使用istreambuf_iterator。
istreambuf_iterator<char>对象进入流的缓冲区,并直接读取下一个字符。(更明确地说,一个istreambuf_iterator<char> 对象从一个istream s中读取会调用s.rdbuf()->sgetc()来读s的下一个字符。)
把我们的文件读取代码改为使用istreambuf_iterator相当简单:
ifstream inputFile("d:\\test.plist");
string fileData((istreambuf_iterator<char>(inputFile)), istreambuf_iterator<char>());
注意这里不需要“unset”skipws标志,istreambuf_iterator不忽略任何字符。它们只抓取流缓冲区的下一个字符。
相对于istream_iterator,它们抓取得更快——在我进行的简单测试中能快40%,如果你的结果不同也不用惊奇。如果随时间流逝,速度优势不断增加也不必奇怪,
因为istreambuf_iterator存在于STL的一个不常访问的角落,所以实现还没有花很多时间来优化。
比如,在我用过的一个实现中,istreambuf_iterator在我的主要测试中只比istream_iterator快了大约5%。那样的实现显然还有很多余地来优化它们的istreambuf_iterator实现。
如果你需要一个一个地读取流中的字符,你不需要格式化输入的威力,你关心的是它们花多少时间来读取流,和明显的性能提高相比,为每个迭代器多键入三个字符的代价是微弱的。
对于无格式的一个一个字符输入,你总是应该考虑使用istreambuf_iterator。
完整代码如下;
#include <iostream>
#include <fstream>
#include <streambuf> std::ifstream file(“d:\\test.plist”);
if (!file.is_open())
{
return NULL;
}
std::string content;
content.assign(std::istreambuf_iterator<char>(file), std::istreambuf_iterator<char>());
注:另外有的程序员使用 ifstream 读取文件内容,然后直接赋值给std::string对象,肯定是错误的。因为:读取的char*类型赋值给string时,默认遇到 \0 就会结束,会丢弃后面的字符。
使用 istreambuf_iterator 读取文件内容,赋值给 std::string的更多相关文章
- shell读取文件内容并进行变量赋值
需求: shell读取文件内容,然后把内容赋值给变量然后进行字符串处理 实现: dataline=$(cat /root/data/data.txt) echo $dataline
- 使用while和read命令读取文件内容
转:使用while和read命令读取文件内容 1.准备数据文件 $cat a.txt 200:2 300:3 400:4 500:5 2.用while循环从文件中读取数据 #!/bin/ksh whi ...
- shell读取文件内容
Shell脚本,执行解释速度快.代码简单易于理解.在shell代码编写过程中,经常会用到读取文件内容. 写法一: ------------------------------------ ...
- Python跳过第一行读取文件内容
Python编程时,经常需要跳过第一行读取文件内容.比较容易想到是为每行设置一个line_num,然后判断line_num是否为1,如果不等于1,则进行读取操作.相应的Python代码如下: inpu ...
- 用c#读取文件内容中文是乱码的解决方法:
用c#读取文件内容中文是乱码的解决方法: //方法1: StreamReader din = new StreamReader(@"C:\1.txt", System.Text.E ...
- android按行读取文件内容的几个方法
一.简单版 import java.io.FileInputStream; void readFileOnLine(){ String strFileName = "Filename.txt ...
- android逐行读取文件内容以及保存为文件
用于长时间使用的apk,并且有规律性的数据 1,逐行读取文件内容 //首先定义一个数据类型,用于保存读取文件的内容 class WeightRecord { String timestamp; flo ...
- 7 RandomAccessFile读取文件内容保存--简单例子(需要验证)
import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.*; /** * 读取动态产生的文件内容 */ publ ...
- node遍历文件夹并读取文件内容
var fs = require('fs'); var path = require('path');//解析需要遍历的文件夹 var filePath = path.resolve('./dist' ...
随机推荐
- 七个月学习Python大计
仅以此篇纪念学习Python征程的开始
- 20145319 《网络渗透》URL攻击
20145319 <网络渗透>URL攻击 实验步骤 首先启动apache2,打开我们的钓鱼网页,键入命令/etc/init.d/apache2 start 在浏览器中尝试着访问自己的ip地 ...
- linux内核分析 第5章读书笔记
第五章 系统调用 一.与内核通信 系统调用在用户控件进程和硬件设备之间添加了一个中间层,作用有: 为用户空间提供了一种硬件的抽象接口 系统调用保证了系统的稳定和安全 每个进程都运行在虚拟系统中,而在用 ...
- 将Sublime Text 添加到鼠标右键菜单的教程方法
安装notepad++软件,在菜单右键自动会添加“edit with notepad++"的选项,那么怎么将Sublime Text 添加到鼠标右键菜单呢?下面是我的操作过程,希望有帮助! ...
- hdu 6444 Neko's loop 单调队列优化DP
Neko's loop Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total ...
- java中子类实例化过程中的内存分配
知识点: 子类继承父类之后,实例化子类时,内存中子类是如何分配内存的呢? 下面,自己会结合一个例子,解释一下,一个子类实例化过程中,内存是如何分配的 参考博客:http://www.cnblogs.c ...
- WebApi——json返回多了 k_BackingField
产生原因: model类添加了 [System.Serializable] 解决方案: xxxxx.WebApi\App_Start\WebApiConfig.cs的Register函数中添加如 ...
- input标签type=button时,如何禁用和开启按钮
本文为博主原创,未经允许不得转载: <input id="exportCameraButton" type="button" class="bt ...
- NS3 fifth.cc 拥塞窗口实例
fifth.cc /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ /* * This progr ...
- 回顾:C++开篇课堂
周三,在刚刚结束矩阵分析的考试之后,面向对象程序设计课正式开始了C++的学习,这次课的重点即是面向对象思想的理解. 梳理一下知识点. C++中函数的默认参数 在函数声明或者在函数定义时,对参数赋初始值 ...