第八章 IO
io库类型和头文件
IO对象无拷贝或赋值
- 不能拷贝,因此不能将形参和返回类型设置为流类型。
- 通常以引用的方式传递和返回流。
- 读写一个IO对象会改变其状态,所以传递和返回的引用不能是const的。
ofstream out1, out2;
out1 = out2; //错误,不能对流对象赋值
ofstream print(out1); //错误,不能初始化ofstream参数
out2 = print(out2); //错误,不能拷贝流对象
条件状态
IO 库定义了4个 iostate 类型的 constexpr 值,表示特定的位模式。
clear(): 复位,清除所有错误标志位。
clear(args): args:iostate值,表示流的新状态。
//复位failbit和badbit,保持其他标志位不变
cin.clear(cin.rdstate() & ~cin.failbit & ~cin.badbit); //对failbit 和 badbit 取反, 然后和初始状态&置零。
管理输出缓冲
缓冲刷新:
-
程序正常结束,作为main函数的return操作的一部分, 缓冲刷新被执行。
-
缓冲区满时,需要刷新缓冲,而后新的数据才能继续写入缓冲区。
-
使用操纵符如 endl, flush, ends 来显式刷新缓冲区.
- endl: 换行,刷新缓冲区。
- flush: 只刷新缓冲区。
- ends:输出空格,刷新缓冲区。
-
在每个输出操作之后,我们可以用操纵符 unitbuf 设置流的内部状态,来清空缓冲区。默认情况下,对cerr是设置 unitbuf 的,因此写到 cerr 的内容都是立即刷新的。
cout << unitbuf; //所有输出操作之后都会立马刷新缓冲区 cout << unitbuf; //回到正常缓冲的方式
-
一个输出流可能被关联到另一个流。在这种情况下,当读写被关联的流时,关联到的流的缓冲区会被刷新。例如,默认情况下,cin 和 cerr 都关联到 cout 。因此,读 cin 或写 cerr 都会导致 cout 的缓冲区被刷新。
cout << cin.rdstate() << endl;//查看错误状态
cin.clear(); //清理错误表示符
cout << cin.rdstate() << endl;//再次查看错误状态 对应0 无错误
- 如果程序崩溃,输出缓冲区不会被刷新。
关联输入输出流
交互式系统通常应该关联输入输出流。
tie有两个重载的版本:
- 不带参数,返回指向所关联的输出流的指针,如果未绑定则返回空指针。
- 接受一个指向ofstream的指针的参数,将自己关联到此ofstream,返回上一个绑定的流的指针。
ostream* tie () const; //返回指向绑定的输出流的指针。
ostream* tie (ostream* tiestr); //将tiestr指向的输出流绑定到该对象上,并返回上一个绑定的输出流指针。
cin.tie(&cout); //仅作展示:标准库已经将cin 和 cout 关联到一起;
// old_tie 指向 cin 先前绑定的流 cout
ostream *old_tie = cin.tie(nullptr); //此时 cin 不与任何流关联
cin.tie(&cerr); // cin 关联到 cerr
cin.tie(old_tie); // cin 关联到 cout
每个流最多同时关联一个流,但多个流可以可以同时关联到同一个ofstream。
文件输入输出
- 对一个已经打开的文件流调用open会失败,并会导致failbit被置位。
- 为了将文件流关联到另一个文件,必须先关闭已经关联的文件,然后关联新的文件。
- 当一个fstream对象被销毁时,close会自动调用。
文件模式
-
保留被ofstream打开的文件中已有数据的唯一方法是显式指定app或in模式。
-
在每次打开文件时,都要设置文件模式,可能是显式地设置,也可能是隐式地设置。当程序未指定模式时,就使用默认值。