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