C++ 学习笔记之(8)-IO 库
IO
库定义了读写内置类型值的操作。此外,一些类,如string
,会自定义类似IO
操作,读写本身对象
IO
类
为了支持不同种类的IO
处理操作,比如读写宽字符,string
类,文件等,在istream
和ostream
之外,标准库还定义了其他一些IO
类型
- 以
w
开头的类型用来处理wchar_t
类型数据,即宽字符语言
IO
对象无拷贝或赋值
进行
IO
操作的函数通常以引用方式传递和返回流读写
IO
对象会改变其状态,故传递和返回的引用不能是const
的ofstream out1, out2; out1 = out2; // 错误:不能对流对象赋值 ofstream print(ofstream); // 错误:不能初始化 ofstream 参数 out2 = print(out2); // 错误:不能拷贝流对象
条件状态
IO
类定义了一些函数和标志,用来访问和操纵流的条件状态
查询流的状态
badbit
表示系统级错误,比如不可恢复的读写错误。一旦badbit
被置位,流就无法再使用failbit
:表示可恢复错误,比如期望读取数值却读出字符等,可修正,流可以继续使用eofbit
和failbit
:表示达到文件结束为止,两个都会被置位goodbit
值为0
,表示流未发生错误
管理输出缓冲
- 每个输出流都管理一个缓冲区,用来保存程序读写的数据
- 导致缓冲刷新(即,数据真正写到输出设备或文件)的原因有很多:
- 程序正常结束,作为
main
函数的return
操作的一部分,缓冲刷新被执行 - 缓冲区满时,需要刷新缓冲,而后新的数据才能继续写入缓冲区
- 使用
endl
、flush
和ends
操纵符显示刷新缓冲区 - 使用操纵符
unitbuf
设置流的内部状态,清空缓冲区。默认情况下,cerr
是设置unitbuf
的,故写到cerr
的内容都是立即刷新的 - 一个输出流可能被关联到另一个流,当读写被关联的流时,关联到的流的缓冲区会被刷新。默认
cin
和cerr
都关联到cout
,故读cin
或写cerr
都会导致cout
的缓冲区被刷新
- 程序正常结束,作为
- 关联流使用
tie
函数 - 每个流同时最多关联到一个流,但多个流可以同时关联到同一个
ostream
cout << "hi!" << endl; // 输出 hi 和一个换行,然后刷新缓冲区
cout << "hi!" << flush; // 输出 hi,然后刷新缓冲区,不附加任何额外字符
cout << "hi!" << ends; // 输出 hi 和一个空字符,然后刷新缓冲区
cout << unitbuf; // 开启后,所有输出操作后都会立即刷新缓冲区,无缓冲
cout << nounitbuf; // 回到正常的缓冲方式
文件输入输出
头文件fstream
定义了三个类型来支持IO
,除了继承自iostream
类型的行为以外,fstream
还增加了一些新的成员管理与流关联的文件
使用文件流对象
使用该文件流对象,将对象与文件关联,进行文件读写操作
open
函数能将空文件流对象与文件关联起来,若调用open
失败,则failbit
会被置位。若想让文件流关联到另外的文件,则必须首先关闭已经关联的文件,使用close
函数- 当一个
fstream
对象被被销毁时,close
会自动被调用
文件模式
每个流都有一个关联的 文件模式, 用来指出如何使用文件
- 只可以对
ofstream
或fstream
对象设定out
模式, 且ofstream
关联文件默认以out
模式打开,fstream
文件默认以in
和out
模式打开 - 只可以对
ifstream
或fstream
对象设定in
模式, 且ifstream
关联文件默认以in
模式打开 - 只有当
out
也被设定时才可以设定trunc
模式 - 只要
trunc
没被设定,就可以设定app
模式。在app
模式下,即使没有显示指定out
模式,文件页以输出方式打开 - 默认情况下,以
out
模式打开的文件也会被截断。要保留文件内容,可以同时指定app
模式或in
模式 ate
和binary
模式可用于任何类型的文件流对象,且可以和其他模式组合使用
文件打开时,都要设置文件模式,可显示设置,也可隐式设置。当未指定模式时,会使用默认值
string
流
sstream
头文件,定义了三个类型来支持内存IO
, 这些类型可以向string
读写数据
结语
C++ 使用标准库类来处理面向流的输入和输出
iostream
处理控制台IO
fstream
处理命名文件IO
sstringstream
完成内存string
的IO
- 类
fstream
和stringstream
都是继承自类iostream
的,输入类都继承自istream
, 输出类都继承自ostream
.