《C++ Primer》 拾遗 第 8 章 IO 库
Notes Cpp Primer
Lastmod: 2021-06-21 周一 20:52:58

第 8 章 IO 库

8.1 IO 类

头文件 类型 作用
iostream istream, wistream 从流读
ostream, wostream 向流写
iostream,wiostream 读写流
fstream ifstream, wifstream 从文件读
ofstream, wofstream 向文件写
fstream, wfstream 读写文件
sstream istringstream, wistringstream 从 string 读
ostringstream, wostringstream 向 string 写
stringstream, wstringstream 读写 string

ifstream 和 istringstream 继承自 istream

ofstream 和 ostringstream 继承自 ostream

IO 对象没有拷贝和赋值操作。

8.1.2 条件状态

IO 类定义的一些函数和标志,可以帮助访问和操纵流的条件状态 condition state

strm 代表某种 IO 类型。s 代表某个流对象。

标志或函数 意义或作用
strm::iostate 及其相关的类型,提供表达条件状态的完整功能
strm::badbit 流已经崩溃
strm::failbit 一个 IO 操作失败了
strm::eofbit 流达到文件为
strm::goodbit 流未处于错误状态,此值保证为 0
s.eof() 若 s 的 eofbit 置位则返回 true
s.fail() 若 s 的 failbit 置位则返回 true
s.bad() 若 s 的 badbit 置位则返回 true
s.good() 若 s 处于有效状态则返回 true
s.clear() 将 s 的条件状态复位,将流的状态设置为有效。返回 void
s.clear(flags) 根据给定的 flags 标志为,将流中对应状态位复位。flags 类型为 strm::iostate。返回 void
s.setstate(flags) 根据给定的 flags 标志为,将流中对应状态位置位。flags 类型为 strm::iostate。返回 void
s.rdstate() 返回流 s 的当前条件状态,返回值类型为 strm::iostate

我们可以将流作为条件使用来检查它的状态。

8.1.3 管理输出缓冲

输出的文本可能立即打印出来,也可能被保存到缓冲区随后再打印。

导致缓冲刷新可能是以下原因:

程序正常结束,作为 main 函数的 return 操作的一部分,缓冲刷新被执行。

缓冲区满。

可以使用 endl 等显式刷新缓冲区。

每个输出操作后可以用 unitbuf 设置流的内部状态来清空缓冲区。默认情况下,对 cerr 是设置 unitbuf 的,因此写到 cerr 的内容都是立即刷新的。

一个输出流可能被关联到另一个流。这种情况下,当读写被关联的流时,关联到的流的缓冲区会刷新。例如默认情况下,cin 和 cerr 都关联到 cout。因此读 cin 或写 cerr 都会导致 cout 的缓冲区被刷新。

注意程序异常终止时输出缓冲区不会被刷新。

刷新输出缓冲区
cout << endl; // 在缓冲区插入一个换行,然后刷新缓冲区
cout << flush; // 刷新缓冲区
cout << ends; // 在缓冲区插入一个空字符,然后刷新缓冲区
unitbuf 操纵符
cout << unitbuf; // 所有输出操作后都会立即刷新缓冲区
cout << nounitbuf; // 回到正常的缓冲方式
关联输入和输出流

注意交互式系统通常应该关联输入流和输出流。

cin.tie(); // 返回关联的输出流的指针,或未关联到流时返回空指针。
cin.tie(postrm); // 传入一个指向 ostream 的指针使其关联到对应的输出流

8.2 文件输入输出

fstream 特有的操作

fstream fstrm;    // 创建未绑定的文件流。 
fstream fstrm(s); // 创建 fstream 并打开名为 s 的文件,
				  // s 可以是 string 或 c 风格字符串的指针
                  // 默认文件模式依赖于 fstream 的类型
fstream fstrm(s, mode); // 创建 fstream 并打开名为 s 的文件,
                        // 并指定 mode
fstrm.open(s);   // 打开名为 s 的文件并将文件与 fstrm 绑定,
                 // mode 依赖于 fstream 类型。返回 void
fstrm.close();   // 关闭与 fstrm 绑定的文件。返回 void。
fstrm.is_open(); // 返回 bool 指出与 fstrm 关联的文件是否成功打开
                 // 且尚未关闭

8.2.1 使用文件流对象

可以使用 fstream 代替 iostream&

成员函数 open 和 close

注意 open 可能会失败,因此应该在使用前检查流状态。

已经打开的文件流调用 open 会导致 failbit 被置位。

可以将文件流关联到另外的文件,此时需要先关闭已经关联的文件,成功关闭后再关联到新的文件。

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

8.2.2 文件模式

file mode

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

只可以对 ifsteam 或 fstream 设定 in

只可以对 ofstream 或 fstream 设定 out

只有当 out 被设定时可以设定 trunc

trunc 没被设定时可以设置 app。app 设定时即便没有 out 也总以输出方式打开。

某人状况即便不指定 trunc,以 out 模式打开的文件也会被截断,想保留内容必须同时指定 app,或者同时制指定 in

ate 和 binary 可以用于任何文件流对象。

ifstream 默认 in

ofstream 默认 out

fstream 默认 in 和 out

注意每次调用 open 时会重新确定打开模式。

8.3 string 流

sstream 头文件定义了 3 个类型来支持内存 IO。

sstream strm;    // 未绑定的 stringstream
sstream strm(s); // 保存 s 的拷贝
strm.str()       // 返回 strm 所保存的 string 的拷贝
strm.str(s)      // 将 string s 拷贝到 strm 中,返回 void。
Prev: 《C++ Primer》 拾遗 第 7 章 类
Next: 《C++ Primer》 拾遗 第 9 章 顺序容器