类型ifstream和istringstream都继承自istream。
类型ofsteram和ostringstream都继承自ostream。
ofstream out1, out2;
out1 = out2; // 错误:不能对流对象赋值
ofstream print(ofstream); // 错误:不能初始化ofstream参数
out2 = print(out2); // 错误:不能拷贝流对象
由于不能拷贝流对象,因此我们不能将形参或返回值类型设置为流类型。
进行IO操作的函数通常以引用方式传递和返回流。
读写一个IO对象会改变其状态,因此传递和返回的引用不能是const的。
IO操作一个与生俱来的问题是可能发生错误。一些错误是可恢复的,而其他错误则发生在系统深处,已经超出了应用程序可以修正的范围。
IO库条件状态:
- | - |
---|---|
strm::iostate | strm是一种IO类型。iostate是一种机器相关的类型,提供了表达条件状态的完整功能 |
strm::badbit | strm::badbit用来指出流已崩溃 |
strm::failbit | strm::failbit用来指出一个IO操作失败了 |
strm::eofbit | strm::eofbit用来指数流达到了文件结束 |
strm::goodbit | strm::gootbit用来指出流未处于错误状态。此值保证为零 |
s.eof() | 若流s的eofbit置位,则返回true |
s.fail() | 若流s的failbit或badbit置位,则返回true |
s.bad() | 若流s的badbit置位,则返回true |
s.good() | 若流s处于有效状态,则返回true |
s.clear() | 将流s中所有条件状态复位,将流的状态设置为有效。返回void |
s.clear(flags) | 根据给定flags标志位,将流s中对应条件状态位复位。flags的类型为strm::iostate。返回void |
s.setstate(flags) | 根据给定的flags标志位,将流s中对应条件状态置位。flags的类型为strm::iostate。返回void |
s.rdstate() | 返回流s的当前状态,返回值类型为strm::iostate |
一个流一旦发生错误,其上后续的IO操作都会失败。
只有当流处于无错状态时,我们才可以从它读取数据,向他写入数据。
代码通常应该在使用一个流之前检查它是否处于良好状态。
确定一个流对象的状态的最简单的方法是将它作为一个条件来使用:
while (cin >> word) {// ok: 读操作成功...
}
将流作为条件使用,只能告诉我们流是否有效,而无法告诉我们具体发生了什么。
有时我们也需要知道流为什么失败。例如,在键入文件结束符标识后我们的应对措施,可能与遇到一个IO设备错误的处理方式是不同的。
IO库定义了一个与机器无关的iostate类型。这个类型应作为一个位集合来使用。
IO库定义了4个iostate类型的constexpr值,表示特定的位模式。这些值用来表示特定类型的IO条件,可以与位运算符一起使用来一次检测或设置多个标志位。
如果badbit、failbit和eofbit任一个被置位,则检测流状态的条件会失败。
标准库还定义了一组函数来查询这些标志位的状态:
向输出流输出数据时,有可能被操作系统保存在缓冲区中,随后再输出到目标。
刷新缓冲区:
unitbuf操纵符:
如果想在每次输出操作之后都刷新缓冲区,我们可以用unitbuf操纵符。它告诉流在接下来的每次写操作之后都进行一次flush操作。而nounitbuf操纵符则重置流,使其恢复正常的系统管理的缓冲区刷新机制。
默认情况下,对cerr是设置unitbuf的,因此写到cerr的内容都是立即刷新的。
注意:如果程序异常终止,输出缓冲区是不会被刷新的。当一个程序崩溃后,它所输出的数据很可能停留在输出缓冲区中等待打印。
除了继承自iostream类型的行为之外,fstream还增加了一些新的成员来管理与流关联的文件。
我们可以对fstream、ifstream和ofstream对象调用这些操作。
- | - |
---|---|
fstream fstrm; | 创建一个未绑定的文件流。fstream是头文件fstream中定义的一个类型。 |
fstream fstrm(s); | 创建一个fstream,并打开名为s的文件。默认的文件模式mode依赖于fstream的类型。 |
fstream fstrm(s, mode); | 与前一个构造函数类似,但按指定mode打开文件。 |
fstrm.open(s) | 打开名为s的文件,并将文件与fstrm绑定。默认的文件mode依赖于fstream的类型。 |
fstrm.close() | 关闭与fstrm绑定的文件。返回void |
fstrm.is_open() | 返回一个bool值,指出与fstrm关联的文件是否成功打开且尚未关闭。 |
如果我们定义了一个空文件流对象,可以随后调用open来将它与文件关联起来:
ifstream in(ifile);
ofstream out; // 输出文件流未与任何文件关联
out.open(ifile + ".copy"); // 打开指定文件
如果调用open失败,failbit会被置位。因为调用open可能失败,进行open是否成功的检测通常是一个好习惯:
if (out) { // 检查open是否成功//open成功,我们可以使用文件了
}
对一个已经打开的文件流调用open会失败,并会导致failbit被置位。随后的视图使用文件流的操作都会失败。为了将文件流关联到另外一个文件,必须首先关闭已经关联的文件:
in.close();
in.open(ifile + "2");
当一个fstream对象被销毁时,close会自动被调用。
文件模式 | 含义 |
---|---|
in | 以读方式打开 |
out | 以写方式打开 |
app | 每次读写操作前均定位到文件末尾 |
ate | 打开文件后立即定位到文件末尾 |
trunc | 截断文件 |
binary | 以二进制方式打开 |
文件模式有如下限制:
默认文件模式:
每个文件流类型都定义了一个默认的文件模式。
与ifstream关联的文件默认以in模式打开;与ofstream关联的文件默认以out模式打开;与fstream关联的文件默认以in和out模式打开。
每次打开文件时,都要设置文件模式,可能时显式地设置,也可能是隐式地设置:
ofstrean out;
out.open("test1.txt"); // 隐含设置为输出和截断
out.close()
out.open("test2.txt", ofstream::app); // 设置为输出和追加
out.close()