为了读取一个文件,我们需要:
- 知道文件名。
- (以读模式)打开文件。
- 读出字符。
- 关闭文件(虽然通常文件会被隐式地关闭)。
为了写一个文件,我们需要:
- 指定文件名。
- 按照指定的文件名,(以写模式)打开文件或创建一个新文件。
- 写入我们的对象。
- 关闭文件(虽然通常文件会被隐式地关闭)。
ifstream是用于读取文件的istream流,ofstream是用于写文件的ostream流,fstream是用于对文件进行读写的iostream流,文件流必须与某个文件相关联,才可使用。例如:
cout << "Please enter input file name:";
string iname;
cin >> iname;
ifstream ist{iname}; //ist是以iname命名的文件对应的输入流
if(!ist) error("can't open input file ", iname);
用一个名字字符串定义一个ifstream,可以打开以该字符串为名的文件进行读操作。!ist检查文件是否成功打开。如果成功打开,我们可以像处理其他任何istream那样从文件中读取数据。例如:
vector<Point> points;
for(Point p; ist>>p; )
points.push_back(p);
写文件的过程与读文件类似,通过流ofstream来实现,例如:
cout << "Please enter name of output file:";
string oname;
cin >> oname;
ofstream ost{oname}; //ost是以oname命名的文件对应的输出流
if(!ost) error("can't open output file ", oname);
!ost检测文件是否成功打开。如果打开成功,我们就可以像处理其他ostream对象一样向文件中写入数据,如:
for(int p:points)
ost << '(' << p.x << ',' << p.y << ")\n";
当一个文件流离开其作用域,与之关联的文件就会被关闭。当文件被关闭时,与之关联的缓冲区会被刷新,也就是说,缓冲区中的字符会被写入到文件中。理想的方法是在创建ostream或istream对象时隐式打开文件,并依靠流对象的作用域来关闭文件。
istream将所有可能的情况归结为四类,称为流状态(stream state):
流状态 | |
good() | 操作成功 |
eof() | 到达输入末尾(“文件尾”) |
fail() | 发生某些意外情况(如,希望读取数字,却读入字符'x') |
bad() | 发生严重意外(如磁盘故障) |
int i=0;
cin >> i;
if(!cin){
//只有输入操作失败, 才会跳转到这里
if(cin.bad()) error("cin is bad");
if(cin.eof()) {
//没有任何输入
//这是我们结束程序经常需要的输入输出操作序列
}
if(cin.fail()) //流遇到了一些意外情况
{
cin.clear(); //为更多的输入操作做准备
//恢复流的其他操作
}
}
!cin可以理解为“cin不成功”或者“cin发生了某些错误”或者“cin的状态不是good()”。在执行cin.clear()后,cin的状态就变为good()。
与istream一样ostream也有四个状态:good()、fail()、eof()和bad()。