【C++Primer笔记】第八章 IO库

第八章 IO库
C++使用标准库类来处理面向流的输入和输出:
·iostream处理控制台IO
·fstream处理命名文件IO
·stringstream完成内存string的IO
类fstream和stringstream都是继承自类iostream的。输入类都继承自istream.,输出类都继承自ostream。因此,可以在istream对象上执行的操作,也可在ifstream或istringstream对象上执行。继承自ostream的输出类也有类似情况。
每个IO对象都维护一组条件状态,用来指出此对象上是否可以进行IO操作。如果遇到了错误一例如在输入流上遇到了文件末尾,则对象的状态变为失效,所有后续输入操作都不能执行,直至错误被纠正。标准库提供了一组函数,用来设置和检测这些状态。

三个独立的头文件中:iostream定义了用于读写流的基本类型,fstream定义了读写命名文件的类型,sstream定义了读写内存string对象的类型。

头文件
类型
iostream
istream,wistream从流读取数据
ostream,wostream向流写入数据
iostream,wiostream读写流

fstream
ifstream,wifstream从文件读取数据
ofstream,wofstream向文件写入数据
fstream,wfstream读写文件

sstream
istringstream,wistringstream从string读取数据
ostringstream,wostringstream向string写入数据
stringstream,wstringstream读写string

ofstream outl,out2;
out1=out2;//错误:不能对流对象赋值
ofstream print (ofstream);//错误:不能初始化ofstream参数
out2=print (out2);//错误:不能拷贝流对象

1O库条件状态
 查询流的状态
 管理条件状态

每个输出流都管理一个缓冲区,用来保存程序读写的数据。
有了缓冲机制,操作系统就可以将程序的多个输出操作组合成单一的系统级写操作。由于设备的写操作可能很耗时,允许操作系统将多个输出操作组合为单一的设备写操作可以带来很大的性能提升。

导致缓冲刷新(即,数据真正写到输出设备或文件)的原因有很多:
程序正常结束,作为main函数的return操作的一部分,缓冲刷新被执行。
缓冲区满时,需要刷新缓冲,而后新的数据才能继续写入缓冲区。
我们可以使用操纵符如end1来显式刷新缓冲区。
在每个输出操作之后,我们可以用操纵符unitbuf设置流的内部状态,来清空缓冲区。默认情况下,对cerr是设置unitbuf的,因此写到cerr的内容都是立即刷新的。
一个输出流可能被关联到另一个流。在这种情况下,当读写被关联的流时,关联到的流的缓冲区会被刷新。例如,默认情况下,cin和cerr都关联到cout。因此,读cin或写cerr都会导致cout的缓冲区被刷新。

刷新输出缓冲区
我们已经使用过操纵符end1,它完成换行并刷新缓冲区的工作。
flush刷新缓冲区,但不输出任何额外的字符
ends向缓冲区插入一个空字符,然后刷新缓冲区:
  cout<<“hi!”<<endl;//输出hi和一个换行,然后刷新缓冲区
cout<<“hi!”<<flush;//输出hi,然后刷新缓冲区,不附加任何额外字符
cout<<“hi!”<<ends;//输出hi和一个空字符,然后刷新缓冲区
   
如果想在每次输出操作后都刷新缓冲区,我们可以使用unitbuf操纵符。它告诉流在接下来的每次写操作之后都进行一次flush操作。而nounitbuf操纵符则重置流,使其恢复使用正常的系统管理的缓冲区刷新机制:
cout <<unitbuf;//所有输出操作后都会立即刷新缓冲区
//任何输出都立即刷新,无缓冲
cout <<nounitbuf;//回到正常的缓冲方式

如果程序异常终止,输出缓冲区是不会被刷新的。当一个程序崩溃后,它所输出的数据很可能停留在输出缓冲区中等待打印。
当调试一个已经崩溃的程序时,需要确认那些你认为已经输出的数据确实已经刷新了。否则,可能将大量时间浪费在追踪代码为什么没有执行上,而实际上代码已经执行了,只是程序崩溃后缓冲区没有被刷新,输出数据被挂起没有打印而已。

当一个fstream对象被销毁时,close会自动被调用。

文件模式
in以读方式打开
out以写方式打开
app每次写操作前均定位到文件末尾
ate打开文件后立即定位到文件末尾
trunc截断文件
binary以二进制方式进行IO

无论用哪种方式打开文件,我们都可以指定文件模式,调用open打开文件时可以,用一个文件名初始化流来隐式打开文件时也可以。指定文件模式有如下限制:
只可以对ofstream或fstream对象设定out模式。
只可以对ifstream或fstream对象设定in模式。
只有当out也被设定时才可设定trunc模式。
只要trunc没被设定,就可以设定app模式。在app模式下,即使没有显式指定out模式,文件也总是以输出方式被打开。

默认情况下,即使我们没有指定trunc,以out模式打开的文件也会被截断。为了保留以out模式打开的文件的内容,我们必须同时指定app模式,这样只会将数据追加写到文件末尾:或者同时指定i模式,即打开文件同时进行读写操作。
ate和binary模式可用于任何类型的文件流对象,且可以与其他任何文件模式组合使用。
每个文件流类型都定义了一个默认的文件模式,当我们未指定文件模式时,就使用此默认模式。与ifstream关联的文件默认以in模式打开:与ofstream关联的文件默认以out模式打开:与fstream关联的文件默认以in和out模式打开。

默认情况下,当我们打开一个ofstream时,文件的内容会被丢弃。阻止一个ofstream清空给定文件内容的方法是同时指定app模式:
//在这几条语句中,f11e1都被截断
ofstream out(“file1”);//隐含以输出模式打开文件并截断文件
ofstream out2(“file1”,ofstream::out);//隐含地截断文件
ofstream out3(“filel”,ofstream:out | ofstream:trunc);
//为了保留文件内容,我们必须显式指定app模式
ofstream app(“file2”,ofstream::app);//隐含为输出模式
ofstream app2(“file2”,ofstream:out | ofstream:app);

保留被ofstream打开的文件中已有数据的唯一方法是显式指定app或in模式。

每次调用open时都会确定文件模式
对于一个给定流,每当打开文件时,都可以改变其文件模式。
ofstream out;//未指定文件打开模式
out.open(“scratchpad”);//模式隐含设置为输出和截断
out.c1ose();//关闭out,以便我们将其用于其他文件
out.open(“precious”,ofstream::app);//模式为输出和追加
out.close();
第一个open调用未显式指定输出模式,文件隐式地以out模式打开。通常情况下,out模式意味着同时使用trunc模式。因此,当前目录下名为scratchpad的文件的内容将被清空。当打开名为precious的文件时,我们指定了append模式。文件中已有的数据都得以保留,所有写操作都在文件末尾进行。
在每次打开文件时,都要设置文件模式,可能是显式地设置,也可能是隐式地设置。当程序未指定模式时,就使用默认值。

sstream头文件定义了三个类型来支持内存IO
istringstream从string读取数据,ostringstream向string写入数据,
而头文件stringstream既可从string读数据也可向string写数据。与fstream类型类似,头文件sstream中定义的类型都继承自我们已经使用过的iostream头文件中定义的类型。
除了继承得来的操作,sstream中定义的类型还增加了一些成员来管理与流相关联的string。
stringstream特有的操作
sstream strm;strm是一个未绑定的stringstream对象。sstream是头文件sstream中定义的一个类型
sstream strm(s);strm是一个sstream对象,保存strings的一个拷贝。此构造函数是exp1icit的
strm.str()返回strm所保存的string的拷贝
strm.str(s)将string s拷贝到strm中。返回void
可以对stringstream对象调用这些操作,但不能对其他O类型调用这些操作。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值