C++ Primer 第八章:IO 库核心要点解析
8.1 IO 类体系
标准库提供三组主要的 IO 类型:
- iostream:包含 istream(输入流)、ostream(输出流)和 iostream(双向流)
- fstream:包含 ifstream(文件输入流)、ofstream(文件输出流)和 fstream(文件双向流),继承自 iostream 体系
- sstream:包含 istringstream(字符串输入流)、ostringstream(字符串输出流)和 stringstream(字符串双向流),同样继承自 iostream 体系
宽字符版本使用 wcin、wcout、wcerr 替代 cin、cout、cerr 来处理 wchar_t 类型。
IO 对象的限制
IO 对象无法进行拷贝或赋值操作,但可以通过引用方式作为函数参数或返回值传递,从而实现输入输出功能。
流状态管理
每个流对象维护一个 iostate 类型的状态值,包含以下位标记:
- badbit:流发生不可恢复错误
- failbit:操作失败(如类型不匹配)
- eofbit:到达文件结束位置
- goodbit:流状态正常(值为 0)
常用状态查询函数:
stream.eof() // 检查 eofbit
stream.fail() // 检查 failbit
stream.bad() // 检查 badbit
stream.good() // 检查 goodbit
状态控制方法:
stream.clear() // 重置所有状态位
stream.clear(flags) // 设置为指定状态
stream.setstate(flags) // 添加指定状态位
auto st = stream.rdstate() // 返回当前 iostate 值
输出缓冲机制
系统为提升性能,会将多次输出暂存到缓冲区,待缓冲区满或特定时机统一输出。
触发缓冲区刷新的条件:
- 程序正常终止
- 缓冲区容量达到上限
- 主动使用 endl 操纵符
- 设置 cout << unitbuf(cerr 默认已启用)
- cin 或 cerr 操作时会自动刷新 cout(因为与 cout 绑定)
注意:程序异常崩溃时缓冲区内容不会被刷新,可能导致部分输出丢失。
8.2 文件输入输出
由于 ifstream、ofstream、fstream 分别继承自 istream、ostream、iostream,所有流操作符(如 >>、<<、getline)均可直接使用。
文件打开方式
ifstream input(fileName); // 以读模式打开
ofstream output;
output.open(fileName + ".bak"); // 以写模式打开
output.close(); // 关闭后再打开其他文件
在函数内定义的流对象,当函数结束时会自动关闭关联文件。
文件打开模式
| in | 只读模式 |
| out | 写入模式(默认会清空文件) |
| app | 追加写入 |
| ate | 打开后定位到文件尾 |
| trunc | 截断文件(out 模式下默认启用) |
| binary | 二进制模式 |
ofstream out1("data.txt"); // out + trunc
ofstream out2("log.txt", ofstream::app); // 追加模式
8.3 字符串流
头文件 sstream 提供的内存 IO 功能,基于 string 进行读写而非文件。
关键操作:
sstream strm; // 创建空流
sstream strm(s); // 拷贝字符串 s 到流中
strm.str(); // 返回流中存储的字符串
strm.str(s); // 将 s 内容复制到流中
strm.clear(); // 清空内容(重复使用前必须调用)
示例代码:
string records("alice 1988 2034");
string name, token;
vector<string> items;
istringstream input(records);
input >> name;
while (input >> token) {
items.push_back(token);
}