基本技能11.7: 打开和关闭文件
在C++中,是通过把文件和流进行关联来打开文件的。正如我们知道的那样,有三种类型的流:输入流,输出流,以及输入/输出流。我们通过声明ifstream类的流对象来生成一个输入流;通过声明ofstream类的流对象来生成输出流;同时需要进行输入和输出的流必须声明为fstream类。例如,下面的代码段创建了一个输入流,一个输出流和一个能同时进行输入和输出的流。
ifstream in; //输入流
ofstream out; //输出流
fstream both; //既可以进行输入也可以进行输出的流
一旦我们创建了一个流,我们就可以使用open()方法来把它和一个文件关联起来。这个方法是这三种流都有的。它们的原型如下:
void ifstream::open(const char *filename,
ios::openmode mode = ios::in);
void ofstream::open(const char *finename,
ios::openmode mode = ios::out|ios::truc);
void fstream::open(const char *filename,
ios::openmode mode = ios::in|ios::out);
其中,filename就是文件的名称,其中是可以包含路径的。mode的值决定了文件是以什么方式被打开的。它的取值必须至少是下面的一个。这些值都是ios类(通过他们的基类iso_base)定义的枚举值。
ios::app
ios::ate
ios::binary
ios::in
ios::out
ios::trunk
我们可以通过或(|)运算来把它们合并起来。其中ios::app会使得针对该文件的所有输出都会被追加到文件的末尾。这个值只适用于可用于输出的文件。ios::ate会使得在打开文件的时候查询到文件的末尾;尽管如此,我们还是可以在文件的任意位置进行输入或者输出操作的。
ios::in指定文件可用于输入。
ios::out指定文件可用于输出。
ios::binary指定文件以二进制格式打开。缺省情况下,所有文件都是以文本的模式被打开的。在文本模式打开文件的时候会进行不同的字符转换。例如,控制字符CRLF会被转换为换行。然而,当以二进制格式打开文件的时候,这样的转换是不会发生的。必须注意的是:不管是格式化的文本还是原始数据文件都可以是以二进制或者文本方式打开的;唯一的区别就在于是否进行字符转换。
ios::trunc会使得先前存在的同名文件被销毁,文件长度会被消减为0。当我们使用ofstream输出流的时候,任何先前存在的同名文件都会自动地被销毁,长度消减为0。
下面的代码段就以文本方式打开一个文件进行输出:
ofstream mystream;
mystream.open(“test”);
由于open()方法的参数mode缺省地就是和流的类型是相对应,通常情况下我们没有必要去指明它的值,就像上面的例子那样。(可能会有些编译器并没有实现把fstream::open()方法参数mode缺省值设置为in|out,此时就需要显示指定了。)
如果open()方法打开文件失败了,流对象会在布尔表达式中被当做false值。我们可以利用这一点来使用类似下面的语句来对打开文件操作是否成功进行确认:
if(!mystream)
{
cout << “Cannot open file!.\n”;
//错误处理
}
通常情况下,我们在访问文件前总是应该对open()方法是否成功进行检查。我们还可以使用is_open()方法来完成这个功能。它也是fstream,ifstream和ofstream类的成员,原型如下:
bool is_open();
如果流和打开的文件成功关联了,则返回true,否则返回false。例如,下面的语句用于检查mystream流是否是打开的:
if(!mystream.is_open())
{
cout <<”File is not open.\n”;
//…
}
尽管使用open()方法来打开一个文件是完全正确的,但是大多数情况下我们不这样做。这是因为ifstream,ofstream和fstream都有自动打开文件的构造函数。这些构造函数的参数及其缺省值都是和open()方法一致的。因此,最常用的打开文件的语句如下:
ifstream mystream(“text”);//为输入而打开文件
如果由于某些原因导致文件不能被打开,相关流变量的值也会被当做是false。关闭文件的时候我们使用close()方法。例如,我们使用下面的语句关闭和mystream相关联的文件:
mystream.close();
close()方法不需要任何参数,也不返回任何值。