8.1 IO类
(P278)
标准库定义的一些IO类型,分别定义在三个独立的头文件中:
iostream定义了读写流的基本类型;
fstream定义了读写命名文件的类型;
sstream定义了读写内存string对象的类型。
(一) IO对象无拷贝或赋值
(P279)
(二) 条件状态
1、确定一个流对象的状态的最简单的方法是将它当作一个条件来使用(P280):
while(cin >> word)
//ok:读操作成功
(三) 管理输出缓冲
1、每个输出流都管理一个缓冲区,用来保存程序读写的数据。文本串可能立即打印出来,但也可能被操作系统保存在缓冲区中,随后再打印。(P281)
2、导致缓冲刷新(即,数据真正写到输出设备或文件)的原因有很多(P281):
①程序正常结束,作为main函数的return操作的一部分,缓冲刷新被执行。
②缓冲区满时,需要刷新缓冲,而后新的数据才能继续写入缓冲区。
③使用操纵符(如endl
、flush
、ends
)来显示刷新缓冲区。
cout << "hi!" << endl; //endl能完成换行并刷新缓冲区的工作
cout << "hi!" << flush; //flush刷新缓冲区,但不附加任何额外字符
cout << "hi!" << ends; //ends向缓冲区插入一个空字符,然后刷新缓冲区
④使用操作符unitbuf
设置流的内部状态,清空缓冲区(unitbuf能使每次输出操作后都刷新缓冲区)。默认情况下,对cerr
是设置unitbuf的,因此写到cerr的内容都是立即刷新的。
//unitbuf操纵符告诉流在接下来的每次写操作之后都进行一次flush操作
cout << unitbuf; //所有输出操作台都会立即刷新缓冲区,无缓冲
//nounitbuf操作符则重置流,回到正常的缓冲方式
cout << nounitbuf;
⑤一个输出流可能被关联到另一个流。
注意:如果程序崩毁,输出缓冲区不会被刷新。
3、当一个输入流被关联到一个输出流时,任何试图从输入流读取数据的操作都会先刷新关联的输出流。标准库将cout和cin关联在一起,因此:
cin >> ival;
导致cout的缓冲区被刷新。
8.2 文件输入输出
(一) 使用文件流对象
1、创建文件流对象时,如果提供了一个文件名,则open会自动被调用。(P284)
ifstream in(ifile); //构筑一个ifstream并打开给定文件
(二) 成员函数open和close
1、一个空文件流对象,可以调用open来将它与文件关联起来。(P284)
ofstream out; //输出文件流未与任何文件相关联
out.open(ifile + ".copy"); //打开指定文件
2、对一个已经打开的文件流调用open会失败,并会导致failbit(见P279)被置位。(P285)
3、要将一个已经open的文件流,关联到另外一个文件,必须首先close其已经关联的文件。(P285)
4、当一个fstream对象被销毁时,close会自动被调用。(P285)
练习 8.4:编写函数,以读模式打开一个文件,将其内容读入到一个string的vector中,将每一行作为一个独立的元素存于vector中。
#include<string>
#include<vector>
#include<fstream>
#include<iostream>
using namespace std;
int main(int argc, char** argv)
{
string fileName = "D:/company_SVN/Hanglobal/trunk/TestOrderLibrary/FFMPEG/FFMPEG_0.prv";
vector<string> vstr;
string str;
ifstream output;
output.open(fileName);
if (output.is_open())
{
while (getline(output,str))
{
vstr.push_back(str);
}
}
for (int i = 0; i < vstr.size(); i++)
{
std::cout << vstr.at(i) << std::endl;
}
output.close();
system("pause");
}
(三) 文件模式
1、每个流都有一个关联的文件模式,用来指定如何使用文件。(P286)
2、指定文件模式有如下限制:
3、每个文件流类型都定义了一个默认的文件模式:(P286)
- ifstream关联的文件默认以in模式打开;
- ofstream关联的文件默认以out模式打开;
- fstream关联的文件默认以in和out模式打开。