系列文章目录
17.4.5 文件模式
程序清单17.18 append.cpp
程序清单17.19 binary.cpp
文章目录
17.4.5 文件模式
文件模式描述的是文件将被如何使用:读、写、追加等。将流与文件关联时(无论是使用文件名初始化文件流对象,还是使用open()方法),都可以提供指定文件模式的第二个参数:
ifstream fin("banjo",model);/constructor with mode arqument
ofstream fout();
fout.open("harp",mode2);//open()with mode arguments
ios base 类定义了一个 openmode 类型,用于表示模式;与 fimtflags 和 iostate 类型一样,它也是一种bitmask 类型(以前,其类型为 int)。可以选择 ios base 类中定义的多个常量来指定模式,表 17.7列出了这些常量及其含义。C++文件 I/O作了一些改动,以便与 ANSIC 文件 I/O 兼容。
如果 ifstream 和 ofstream 构造函数以及 open( )方法都接受两个参数,为什么前面的例子只使用一个参数就可以调用它们呢?您可能猜到了,这些类成员函数的原型为第二个参数(文件模式参数)提供了默认值。例如,ifstream open()方法和构造函数用ios base:in(打开文件以读取)作为模式参数的默认值,而ofstream open()方法和构造函数用ios base:out|ios base:trunc(打开文件,以读取并截短文件)作为默认值。位运算符 OR(1)用于将两个位值合并成一个可用于设置两个位的值。fstream 类不提供默认的模式值,因此在创建这种类的对象时,必须显式地提供模式。
注意,ios base::trunc标记意味着打开已有的文件,以接收程序输出时将被截短;也就是说,其以前的内容将被删除。虽然这种行为极大地降低了耗尽磁盘空间的危险,但您也许能够想象到这样的情形,即不希望打开文件时将其内容删除。当然,C++提供了其他的选择。例如,如果要保留文件内容,并在文件尾添加(追加)新信息,则可以使用ios base::app 模式:
ofstream fout("bagels",ios base::outios | base::app);
上述代码也使用|运算符来合并模式,因此ios base::out|ios base::app意味着启用模式out和 app(参见图 17.6)。
老式C++实现之间可能有一些差异。例如,有些实现允许省略前一例子中的iosbase::out,有些则不允许。如果不使用默认模式,则最安全的方法是显式地提供所有的模式元素。有些编译器不支持表17.6中的所有选项,有些则提供了表中没有列出的其他选项。这些差异导致的后果之一是,可能必须对后面的例子作一些修改,使之能够在所用的系统中运行。好在C++标准提供了更高的统一性。
标准 C++根据 ANSIC标准 IO 定义了部分文件 JO。实现像下面这样的 C++语句时:
ifstream fin(filename, c++mode);
就像它使用了C的fopen()函数一样:
fopen(filename, cmode);
其中,c++mode 是一个 openmode 值,如 ios base::in;而 cmode 是相应的℃模式字符串,如“r”表 17.8列出了 C++模式和C模式的对应关系。注意,ios base::out本身将导致文件被截短,但与ios base::in起使用时,不会导致文件被截短。没有列出的组合,如ios base:in[vn]ios base::trunc,将禁止文件被打开。is open()方法用于检测这种故障。
注意,ios_base:ate 和ios_base::app 都将文件指针指向打开的文件尾。二者的区别在于,ios base::app模式只允许将数据添加到文件尾,而iosbase::ate模式将指针放到文件尾。显然,各种模式的组合很多,我们将介绍几种有代表性的组合。
1.追加文件来看一个在文件尾追加数据的程序。
该程序维护一个存储来客清单的文件。该程序首先显示文件当前的内容(如果有话)。在尝试打开文件后,它使用isopen()方法来检查该文件是否存在。接下来,程序以ios_base:app 模式打开文件,进行输出。然后,它请求用户从键盘输入,并将其添加到文件中。最后,程序显示修订后的文件内容。程序清单17.18演示了如何实现这些目标。请注意程序是如何使用isopen()方法来检测文件是否被成功打开的。
注意:在早期,文件 I/0 可能是 C++最不标准的部分,很多老式编译器都不遵守当前的标准。例如,有些编译器使用诸如 nocreate 等模式,而这些模式不是当前标准的组成部分。另外,只有一部分编译器要求在第二次打开同一个文件进行读取之前调用fin.clear()。
程序清单17.18 append.cpp
// append.cpp -- appending information to a file
#include <iostream>
#include <fstream>
#include <string>
#include <cstdlib> // (or stdlib.h) for exit()
const char * file = "guests.txt";
int main()
{
using namespace std;
char ch;
// show initial contents
ifstream fin;
fin.open(file);
if (fin.is_open())
{
cout << "Here are the current contents of the "
<< file << " file:\n";
while (fin.get(ch))
cout << ch;
fin