在打开文件时,无论是调用 open 还是以文件名作为流初始化的一部分,都需指定文件模式(file mode)。每个 fstream 类都定义了一组表示不同模式的值, 用于指定流打开的不同模式。文件模式是整型常量,在打开指定文件时,可用位操作符设置一个或多个模式。文件流构造函数和 open 函数都提供了默认实参设置文件模式。默认值因流类型的不同而不同。此外,还可以显式地以模式打开文件。
in | 打开文件做读操作 |
out | 打开文件做写操作 |
app | 在每次写之前找到文件尾 |
ate | 打开文件后立即将文件定位在文件尾 |
trunc | 打开文件时清空已存在的文件流 |
binary | 以二进制模式进行 IO 操作 |
out、trunc 和 app 模式只能用于指定与 ofstream 或 fstream 对象关联的文件;in 模式只能用于指定与 ifstream 或 fstream 对象关联的文件。所有的文件都可以用 ate 或 binary 模式打开。ate 模式只在打开时有效:文件打开后将定位在文件尾。以 binary 模式打开的流则将文件以字节序列的形式处理,而不解释流中的字符。
默认时,与 ifstream 流对象关联的文件将以 in 模式打开,该模式允许文件做读的操作:与 ofstream 关联的文件则以 out 模式打开,使文件可写。以out 模式打开的文件会被清空:丢弃该文件存储的所有数据。
从效果来看,为 ofstream 对象指定 out 模式等效于同时指定了 out 和 trunc 模式。
对于用 ofstream 打开的文件,要保存文件中存在的数据,唯一方法是显式地指定 app 模式打开:
// output mode by default; truncates file named "file1"
ofstream outfile("file1");
// equivalent effect: "file1" is explicitly truncated
ofstream outfile2("file1", ofstream::out | ofstream::trunc);
// append mode; adds new data at end of existing file named "file2"
ofstream appfile("file2", ofstream::app);
outfile2 的定义使用了按位或操作符将相应的文件同时以out 和 trunc 模式打开。
对同一个文件作输入和输出运算
fstream 对象既可以读也可以写它所关联的文件。fstream 如何使用它的文件取决于打开文件时指定的模式。
默认情况下,fstream 对象以 in 和 out 模式同时打开。当文件同时以 in和 out 打开时不清空。如果打开 fstream 所关联的文件时,只使用 out 模式,而不指定 in 模式,则文件会清空已存在的数据。如果打开文件时指定了 trunc模式,则无论是否同时指定了 in 模式,文件同样会被清空。下面的定义将copyOut 文件同时以输入和输出的模式打开:
// open for input and output
fstream inOut("copyOut", fstream::in | fstream::out);
模式是文件的属性而不是流的属性
每次打开文件时都会设置模式
ofstream outfile;
// output mode set to out, "scratchpad" truncated
outfile.open("scratchpad", ofstream::out);
outfile.close(); // close outfile so we can rebind it
// appends to file named "precious"
outfile.open("precious", ofstream::app);
outfile.close();
// output mode set by default, "out" truncated
outfile.open("out");
第一次调用 open 函数时,指定的模式是 ofstream::out。当前目录中名为“scratchpad”的文件以输出模式打开并清空。而名为“precious”的文件,则要求以添加模式打开:保存文件里的原有数据,所有的新内容在文件尾部写入。
在打开“out”文件时,没有明确指明输出模式,该文件则以 out 模式打开,这意味着当前存储在“out”文件中的任何数据都将被丢弃。
只要调用 open 函数,就要设置文件模式,其模式的设置可以是显式的也可以是隐式的。如果没有指定文件模式,将使用默认值。
打开模式的有效组合
out | 打开文件做写操作,删除文件中已有的数据 |
out | app | 打开文件做写操作,在文件尾写入 |
out | trunc | 与 out 模式相同 |
in | 打开文件做读操作 |
in | out | 打开文件做读、写操作,并定位于文件开头处 |
in | out | trunc | 打开文件做读、写操作,删除文件中已有的数据 |
上述所有的打开模式组合还可以添加 ate 模式。对这些模式添加 ate 只会改变文件打开时的初始化定位, 在第一次读或写之前, 将文件定位于文件末尾处。
一个打开并检查输入文件的程序
// opens in binding it to the given file
ifstream& open_file(ifstream &in, const string &file)
{
in.close(); // close in case it was already open
in.clear(); // clear any existing errors
// if the open fails, the stream will be in an invalid state
in.open(file.c_str()); // open the file we were given
return in; // condition state is good if open succeeded
}
由于不清楚流 in 的当前状态,因此首先调用 close 和 clear 将这个流设置为有效状态。然后尝试打开给定的文件。如果打开失败,流的条件状态将标志这个流是不可用的。最后返回流对象 in,此时,in 要么已经与指定文件绑定起来了,要么处于错误条件状态。