IO库
IO类
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 |
为了支持使用宽字符语言,标准库定义了一组类型和对象来操作wchar_t类型的数据。宽字符版本的类型和函数的名字以一个w开始。
IO类型之间的关系
标准库使我们忽略这些不同类型的流之间的差异,这是通过**继承机制(inheritance)**实现的。
继承机制使我们声明一个特定的类继承自另一个类。我们通常可以将一个派生类(继承类)对象当作其基类(所继承的类)对象来使用。
IO对象无拷贝或赋值
我们不能拷贝或对IO对象赋值。我们也不能将形参或返回类型设置为流类型。进行IO操作的函数通常以引用方式传递和返回流。读写一个IO对象会改变其状态,因此传递和返回的引用不能是const。
条件状态
IO库条件状态
strm::iostate | strm是一种IO类型。iostate是一种机器相关的类型,提供了表达条件状态的完整功能。 |
---|
strm::badbit | 用来指出流已经崩溃 | strm::failbit | 用来指出一个IO操作已经失败 | strm::eofbit | 用来指出流达到了文件结束 | strm::goodbit | 用来指出流未处于错误状态,此值保证为0. | 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操作都会失效。
通常情况下,一旦badbit被置位,流就无法被使用了。在发生可恢复错误后,failbit被置位。如果达到文件结束位置,eofbit和failbit都会被置位。goodbit的值为0,表示流未发生错误。如果badbit、failbit和eofbit任一个被置位,则检测状态的条件会失败。
刷新输出缓冲区
IO库有两个类似的操纵符:flush和end。flush刷新缓冲区,但不输出任何额外的字符;ends向缓冲区插入一个空字符,然后刷新缓冲区。
std::cout << "hi!" << std::endl;
std::cout << "hi!" << std::flush;
std::cout << "hi!" << std::ends;
unitbuf操纵符
如果想在每次输出操作后都刷新缓冲区,我们可以使用unitbuf操纵符。它告诉流在接下来的每次写操作之后都进行一次flush操作。而nounitbuf操纵符则重置流,使其恢复使用正常的系统管理的缓冲区刷新机制:
std::cout << std::unitbuf;
std::cout << std::nounitbuf;
如果程序崩溃,输出缓冲区不会被刷新。
关联输入和输出流
当一个输入流被关联到一个输出流时,任何试图从输入流读取数据的操作都会先刷新关联的输出流。
tie函数有两个版本:
- 不带参数的版本,返回指向输出流的指针。如果本对象当前关联到一个输出流,则返回的就是指向这个流的指针,如果对象未关联到流,则返回空指针。
- 第二个版本接受一个指向ostream的指针,将自己关联到ostream。
我们既可以将istream对象关联到一个ostream,也可以将ostream对象关联到一个ostream对象。
std::cin.tie(&std::cout);
std::ostream *old_tie = std::cin.tie(nullptr);
std::cin.tie(&std::cerr);
std::cin.tie(old_tie);
文件输入输出
头文件fstream定义了三个类型来支持文件IO:ifstream从一个给定文件读取数据,ofstream向一个给定文件写入数据,以及fstream可以读写给定文件。
fstream特有的操作
fstream fstrm; | 创建一个未绑定的文件流。fstream是头文件fstream中定义的一个类型 |
---|
fstream fstrm(s); | 创建一个fstream,并打开名为s的文件。s是一个string类型,或者是一个指向C风格字符串的指针。这些构造函数都是explicit的。默认的文件模式mode依赖于fstream的类型。 | fstream fstrm(s, mode); | 与前一个构造函数类似,按指定mode打开文件。 | fstrm.open(s); | 打开名为s的文件,并将文件与fstrm绑定。s是一个string或一个指向C风格字符串的指针。默认的文件mode依赖于fstream的类型,返回void。 | fstrm.close(s); | 关闭与fstrm绑定的文件。返回void | fstrm.is_open(); | 返回一个bool值,指出与fstrm关联的文件是否成功打开且尚未关闭。 |
在C++新标准中,文件名既可以是库类型string对象,也可以是C风格字符数组。
可以用fstream代替iostream&。
open和close
对一个已经打开的文件流调用open会失败,并会导致failbit被置位。随后的试图使用文件流的操作都会失败,为了将文件流关联到另外一个文件,必须首先关闭已经关联的文件。一旦文件成功关闭,我们可以打开新的文件。
如果open成功,则open会设置流的状态,是的good()为true。
当一个fstream对象被销毁时,close会自动被调用。
文件模式
每个流都有一个关联的文件模式(file mode),用来指出如何使用文件。
in | 以读方式打开 |
---|
out | 以写方式打开 | app | 每次写操作前均定位到文件末尾 | ate | 打开文件后立即定位到文件末尾 | trunc | 截断文件 | binary | 以二进制方式进行IO |
指定文件模式的限制:
- 只可以对ofstream或fstream对象设定out模式。
- 只可以对 ifstream 或 fstream对象设定in模式。
- 只有当out 也被设定时才可以设定trunc模式。
- 只要trunc没被设定,就可以设定app模式。在app模式下,即使没有显示指定out模式,文件也总以输出方式被打开。
- 默认情况下,即使我们没有指定trunc,以out模式打开的文件也会被截断。为了保留以out模式打开的文件的内容,我们必须同时指定app模式,这样只会将数据追加写到文件末尾;或者同时指定in模式,即打开文件同时进行读写操作。
- ate和binary模式可用于任何类型的文件流对象,且可以与其他任何文件模式组合使用。
与istream关联的文件默认以in模式打开;与ostream关联的文件默认以out模式打开;与fstream关联的文件默认以in和out模式打开。
以out模式打开文件会丢弃已有数据
阻止一个ostream清空给定文件内容的方法是同时指定app模式。
通常情况下,out模式意味着同时使用trunc模式。
string流
istringstream从string读取数据,ostringstream向string写入数据,而头文件stringstream既可以从string读取数据也可向string写入数据。
stringstream 特有的操作
sstream strm; | strm是一个未绑定的stringstream对象。sstream是头文件sstream中定义的一个类型。 |
---|
sstream strm(s); | strm是一个sstream对象,保存string s的一个拷贝。此构造函数时explicit的。 | strm.str() | 返回strm所保存的string的拷贝 | strm.str(s) | 将string s拷贝到strm中。返回void。 |
|