IO库
IO类
为了支持使用宽字符的语言,标准库定义了一组类型和对象来操纵 wchar_t 类型的数据。宽字符版本的类型和函数的名字以一个 w 开始。wcin wcout 和 wcerr 是分别对应 cin cout 和 cerr 的宽字符版本对象
IO类型之间的关系
类型 ifstream 和 istringstream 都继承自 istream,因此我们可以像使用 istream 对象一样来使用 ifstream 和 istringstream 对象。
IO对象无拷贝或赋值
我们不能拷贝或对 IO 对象赋值
由于不能拷贝 IO 对象,因此我们不能将形参或返回类型设置为流类型。进行IO操作的函数通常以引用方式传递和返回流,读写一个IO对象会改变其状态,因此传递和返回的引用不能是const的
条件状态
查询流的状态
将流作为条件使用,只能告诉我们流是否有效,而无法告诉我们具体发生了什么。
IO库定义了一个与机器无关的 iostream 类型,它提供了表达流状态的完整功能
管理输出缓存
导致缓冲刷新(即,数据真正写到输出设备或文件)的原因有很多:
- 程序正常结束,作为 main 函数的 return 操作的一部分,缓冲刷新执行
- 缓冲区满时,需要刷新缓冲,而后新的数据才能继续写入缓冲区
- 我们可以使用缓冲操纵符如 endl 来显式刷新缓冲区
- 在每个输出操作之后,我们可以使用操纵夫 unitbuf 设置流的内部状态,来清空缓冲区。默认情况下,对 cerr 是设置 unitbuf 的,因此写到 cerr 的内容都是立即刷新的
- 一个输出流可能被关联到另一个流,在这种情况下,当读写被关联到流时,关联到的流的缓冲区会被刷新。
刷新输出缓冲区
操纵符 endl 完成执行并刷新缓冲区的工作。IO库中还有类似的: flush 和 ends。
flush 刷新缓冲区,但不输出任何额外的字符,ends 向缓冲区插入一个空字符,然后刷新缓冲区
unitbuf 操纵符
unitbuf 操纵符告诉流在接下来的每次写操作之后都进行一次 flush 操作,在每次输出操作之后都刷新缓冲区
nounitbuf 操纵符则重置流,使其恢复使用正常的系统管理的缓冲区刷新机制
关联输入和输出流
当一个输入流被关联到一个输出流时,任何试图从输入流读取数据的操作都会先刷新关联的输出流标准库将 cout 和 cin 关联到一起
tie 有两个重载的版本,一个版本不带参数,返回指向输出流的指针。第二个版本接受一个指向 ostream 的指针,将自己关联到此 ostream。即 x.tie(&o) 将流 x 关联到输出流 o
文件输入输出
使用文件流对象
当我们想要读写一个文件时,可以定义一个文件流对象,并将对象与文件关联起来。每个文件流类都定义一个名为 open 的成员函数,它完成一些系统相关的操作,来定位给定的文件,并视情况打开为读或写模式
用 fstream 代替 iostream&
在要求使用基类型对象的地方,我们可以用继承类型的对象来代替
接受一个 iostream 类型引用(或指针)参数的函数,可以用一个对应的 fstream(或 sstream)类型来调用。如果一个函数接受一个 ostream& 参数,我们在调用这个函数时,可以传递一个 ofstream 对象,对 istream& 和 ifstream 也是类似的
成员函数 open 和 close
如果调用 open 失败,failbit 会被置位。因为调用 open 可能失败,进行 open 是否成功的检测是一个好习惯
为了将文件流关联到另外一个文件,必须首先关闭已经关联的文件,一旦文件成功关闭,我们可以打开新的文件
自动构造和析构
文件模式
每个流都有一个关联的文件模式,用来指出如何使用文件,下表列出了文件模式和他们的含义
以 out 模式打开文件会丢弃已有数据
每次调用 open 时都会确定文件模式
string 流
sstream 头文件定义了三个类型来支持内存 IO,这些类型可以向 string 写入数据,从 string 读取数据,就像 string 是个 IO 流一样
istringstream 从 string 读取数据,ostringtream 向 string 写入数据,而头文件 stringstream既可以从 string 读取数据也可以向 string 写数据。与 fstream 类型类似,头文件 sstream 中定义的类型都继承自 iostream 头文件中定义的类型。除了继承得到的操作, sstream 中定义的类型还增加了一些成员来管理与流相关联的 string。以下操作可以对 stringstream 对象调用,但不能对其他IO类型调用