1, IO 类型在三个独立的头文件中定义:iostream 定义读写控制窗口的类型,fstream 定义读写已命名文件的类型,而 sstream 所定义的类型则用于读写存储在内存中的 string 对象。在 fstream 和 sstream 里定义的每种类型都是从 iostream 头文件中定义的相关类型派生而来。
2, IO标准库类型和头文件
Header |
Type |
---|---|
iostream |
istream 从流中读取 ostream 写到流中去 iostream 对流进行读写;从 istream 和 ostream 派生而来 |
fstream |
ifstream 从文件中读取;由 istream 派生而来 ofstream 写到文件中去;由 ostream 派生而来 fstream 读写文件;由 iostream 派生而来 |
sstream
|
istringstream 从 string 对象中读取;由 istream 派生而来 ostringstream 写到 string 对象中去;由 ostream 派生而来 stringstream 对 string 对象进行读写;由 iostream 派生而来 |
3, 标准库类型不允许做复制或赋值操作,因此不能存储在 vector(或其他)容器中(即不存在存储流对象的 vector 或其他容器)。形参或返回类型也不能为流类型,一般情况下,如果要传递 IO 对象以便对它进行读写,可用非 const 引用的方式传递这个流对象。
3, IO 标准库管理一系列条件状态(condition state)成员,用来标记给定的 IO 对象是否处于可用状态,或者碰到了哪种特定的错误。
strm::iostate |
机器相关的整型名,由各个 iostream 类定义,用于定义条件状态 |
strm::badbit |
strm::iostate 类型的值,用于指出被破坏的流 |
strm::failbit |
strm::iostate 类型的值,用于指出失败的 IO 操作 |
strm::eofbit |
strm::iostate 类型的值,用于指出流已经到达文件结束符 |
s.eof() |
如果设置了流 s 的 eofbit 值,则该函数返回 true |
s.fail() |
如果设置了流 s 的 failbit 值,则该函数返回 true |
s.bad() |
如果设置了流 s 的 badbit 值,则该函数返回 true |
s.good() |
如果流 s 处于有效状态,则该函数返回 true |
s.clear() |
将流 s 中的所有状态值都重设为有效状态 |
s.clear(flag) |
将流 s 中的某个指定条件状态设置为有效。flag 的类型是 strm::iostate |
s.setstate(flag) |
给流 s 添加指定条件。flag 的类型是 strm::iostate |
s.rdstate() |
返回流 s 的当前条件,返回值类型为 strm::iostate |
4, 所有流对象都包含一个条件状态成员,该成员由 setstate 和 clear 操作管理。这个状态成员为 iostate 类型,这是由各个 iostream 类分别定义的机器相关的整型。每个 IO 类还定义了三个 iostate 类型的常量值,分别表示特定的位模式。badbit 标志着系统级的故障,如无法恢复的读写错误。如果出现了这类错误,则该流通常就不能再继续使用了。如果出现的是可恢复的错误,如在希望获得数值型数据时输入了字符,此时则设置 failbit 标志,这种导致设置 failbit 的问题通常是可以修正的。eofbit 是在遇到文件结束符时设置的,此时同时还设置了 failbit。流的状态由 bad、fail、eof 和 good 操作提示。如果 bad、fail 或者 eof 中的任意一个为 true,则检查流本身将显示该流处于错误状态。类似地,如果这三个条件没有一个为 true,则 good 操作将返回 true。
流状态的查询和控制
int ival;
// read cin and test only for EOF; loop is executed even if there are other IO failures
while (cin >> ival, !cin.eof()) {
if (cin.bad()) // input stream is corrupted; bail out throw runtime_error("IO stream corrupted"); if (cin.fail()) { // bad input cerr<< "bad data, try again"; // warn the user cin.clear(istream::failbit); // reset the stream continue; // get next input } // ok to process ival }
5, 文件对象流的使用,假设 ifile 和 ofile 是存储希望读写的文件名的 strings 对象,可如下编写代码:
// construct an ifstream and bind it to the file named ifile
ifstream infile(ifile.c_str());
// ofstream output file object to write file named ofile
ofstream outfile(ofile.c_str());
上述代码定义并打开了一对 fstream 对象。infile 是读的流,而 outfile 则是写的流。为 ifstream 或者 ofstream 对象提供文件名作为初始化式,就相当于打开了特定的文件。在使用 fstream 对象之前,还必须使这些对象捆绑要读写的文件:
ifstream infile; // unbound input file stream
ofstream outfile; // unbound output file stream
infile.open("in"); // open file named "in" in the current directory outfile.open("out"); // open file named "out" in the current directory
if (!infile) 和 if(!outfile)
将文件流与新文件重新捆绑
infile.close(); // closes "in"
infile.open("next"); // opens file named "next" for reading
清除文件状态
input.close(); // close file when we're done with it
input.clear(); // reset state to ok
6,在打开文件时,无论是调用 open 还是以文件名作为流初始化的一部分,都需指定文件模式(file mode)。每个 fstream 类都定义了一组表示不同模式的值,用于指定流打开的不同模式。与条件状态标志一样,文件模式也是整型常量,在打开指定文件时,可用位操作符设置一个或多个模式。
in |
打开文件做读操作 |
out |
打开文件做写操作 |
app |
在每次写之前找到文件尾 |
ate |
打开文件后立即将文件定位在文件尾 |
trunc |
打开文件时清空已存在的文件流 |
binary |
以二进制模式进行 IO 操作 |
// append mode; adds new data at end of existing file named "file2"
ofstream appfile("file2", ofstream::app);
7,iostream 标准库支持内存中的输入/输出,只要将流与存储在程序内存中的 string 对象捆绑起来即可。 与 fstream 类型一样,sstream 类型除了继承的操作外,还各自定义了一个有 string 形参的构造函数,这个构造函数将 string 类型的实参复制给 stringstream 对象。注意到尽管 fstream 和 sstream 共享相同的基类,但它们没有其他相互关系。特别是,stringstream 对象不使用 open 和 close 函数,而 fstream 对象则不允许使用 str。
stringstream 特定的操作:
stringstream strm; |
创建自由的 stringstream 对象 |
stringstream strm(s); |
创建存储 s 的副本的 stringstream 对象,其中 s 是 string 类型的对象 |
strm.str() |
返回 strm 中存储的 string 类型对象 |
strm.str(s) |
将 string 类型的 s 复制给 strm,返回 void |