首页 > 编程笔记

C++打开文件的两种方式(文件流类和open函数)

在C++中,操作(读、写)文件之前必须先打开文件,打开方式有两种,一种是利用文件流类的构造函数,另一种是调用文件流类提供的 open() 成员函数,两种打开方式在效果上是相同的。

文件流类打开文件

C++文件流类提供了更高级的、面向对象的文件操作接口,其中 ifstream 用于读取文件,ofstream 用于写入文件,而 fstream 则可用于读写文件。

所有的文件流类都至少提供了两个版本的构造函数,一个不带参数的默认构造函数和一个带参数的构造函数,参数用于指定目标文件以及打开文件的模式,如下所示:
//ifstream 类的构造函数
ifstream();
explicit ifstream (const char* filename, ios_base::openmode mode = ios_base::in);

//ofstream 类的构造函数
ofstream();
explicit ofstream (const char* filename, ios_base::openmode mode = ios_base::out);

//fstream 类的构造函数
fstream();
explicit fstream (const char* filename, ios_base::openmode mode = ios_base::in | ios_base::out);
其中带参数的构造函数可以直接打开目标文件:
表 1 文件打开模式
模式标记 适用对象 作用
ios::in ifstream
fstream
打开文件用于读取数据。如果文件不存在,则打开出错。
ios::out ofstream
fstream
打开文件用于写入数据。如果文件不存在,则新建该文件;如果文件原来就存在,则打开时清除原来的内容。
ios::app ofstream
fstream
打开文件,用于在其尾部添加数据。如果文件不存在,则新建该文件。
ios::ate ifstream 打开一个已有的文件,并将文件读指针指向文件末尾(读写指 的概念后面解释)。如果文件不存在,则打开出错。
ios:: trunc ofstream 打开文件时会清空内部存储的所有数据,单独使用时与 ios::out 相同。
ios::binary ifstream
ofstream
fstream
以二进制方式打开文件。若不指定此模式,则以文本模式打开。
ios::in | ios::out fstream 打开已存在的文件,既可读取其内容,也可向其写入数据。文件刚打开时,原有内容保持不变。如果文件不存在,则打开出错。
ios::in | ios::out ofstream 打开已存在的文件,可以向其写入数据。文件刚打开时,原有内容保持不变。如果文件不存在,则打开出错。
ios::in | ios::out | ios::trunc fstream 打开文件,既可读取其内容,也可向其写入数据。如果文件本来就存在,则打开时清除原来的内容;如果文件不存在,则新建该文件。

举个简单的例子:
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
    ifstream inFile("c:\\tmp\\test.txt", ios::in);
    if (inFile)
        inFile.close();
    else
        cout << "test.txt doesn't exist" << endl;
   
    ofstream oFile("test1.txt", ios::out);
    if (!oFile)
        cout << "error 1";
    else
        oFile.close();
   
    fstream oFile2("tmp\\test2.txt", ios::out | ios::in);
    if (!oFile2)
        cout << "error 2";
    else
        oFile.close();
    return 0;
}
对于打开的文件,当不再进行任何操作时,要手动调用 close() 成员函数关闭文件。

open()函数打开文件

使用不带参数的构造函数,意味着该文件流对象的目标文件还没有确定。在后面的程序中,可以调用文件流类提供的 open() 成员函数打开指定的文件。

各个文件流的 open() 函数如下:
//std::ifstream::open
void open (const   char* filename, ios_base::openmode mode = ios_base::in);

//std::ofstream::open
void open (const   char* filename, ios_base::openmode mode = ios_base::out);

//std::fstream::open
void open (const char* filename, ios_base::openmode mode = ios_base::in | ios_base::out);
和文件流类的构造函数相比不难看出,open() 成员函数和带参数的构造函数非常相似,其目的也很相似,都是以指定的模式打开指定的文件。

举个简单的例子:
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
    ifstream inFile;
    inFile.open("c:\\tmp\\test.txt", ios::in);
    if (inFile)  //条件成立,则说明文件打开成功
        inFile.close();
    else
        cout << "test.txt doesn't exist" << endl;
   
    ofstream oFile;
    oFile.open("test1.txt", ios::out);
    if (!oFile)  //条件成立,则说明文件打开出错
        cout << "error 1" << endl;
    else
        oFile.close();
   
    oFile.open("tmp\\test2.txt", ios::out | ios::in);
    if (oFile)  //条件成立,则说明文件打开成功
        oFile.close();
    else
        cout << "error 2" << endl;
   
    fstream ioFile;
    ioFile.open("..\\test3.txt", ios::out | ios::in | ios::trunc);
    if (!ioFile)
        cout << "error 3" << endl;
    else
        ioFile.close();
   
    return 0;
}
调用 open() 成员函数时,给出的文件名可以是全路径的,如第 7 行的c:\\tmp\\test.txt, 指明文件在 c 盘的 tmp 文件夹中;也可以只给出文件名,如第 13 行的test1.txt,这种情况下程序会在当前文件夹(也就是可执行程序所在的文件夹)中寻找要打开的文件。

第 18 行的tmp\\test2.txt给出的是相对路径,说明 test2.txt 位于当前文件夹的 tmp 子文件夹中。第 24 行的..\\test3.txt也是相对路径,代表上一层文件夹,此时要到当前文件夹的上一层文件夹中查找 test3.txt。此外,..\\..\\test4.txt..\\tmp\\test4.txt等都是合法的带相对路径的文件名。

使用文件流的 open() 函数打开文件时有一点需要注意,如果该文件流已经打开了一个文件,那么在打开新文件之前,必须关闭当前文件,否则 open() 函数调用会失败。

推荐阅读