C++之文件输入输出
C++之文件输入输出
在c++中我们易知的是cout和cin俩个标准输出输入,而在真实的状况中。我们则是需要对文件的内容进行读取和重新写入,这样我们只有cin和cout这俩个标准输入和输出就明显的不够满足条件了。所以有一个fstream类中的ifstream和ofstream则解决了这个对文件操作的问题。
1.文件输入:
我们相比较和之前的标准输出一起来试一下:
| 标准输出 | 文件输入 | 
|---|---|
| 包含头文件iostream类 | 包含头文件fstream类 | 
| 定义了ostream类 | 定义了ofstream类 | 
| ostream声明了一个cout对象 | ofstream声明了fout(一个或多个自己命名)对象 | 
| 必须指明命名空间std::(cout和endl) | 必须指明命名空间std:: | 
| 结合cout与运算符<<一起显示各种数据 | 需要将之前创建的对象和文件相关联起来(open方法) 也和标准输入一样和运算符<<搭配使用 | 
| … | 使用完成后需要将对象close() | 
如下实例:
#include <iostream>
#include <fstream>
using namespace std;
int main(){
    //标准输出(写到显示屏幕上)
    char ch[] = "hello world!";
    cout << ch << endl; 
    //文件输入(写到文件里)
    ofstream fout;
    fout.open("data.txt");//将fout对象和文件绑定起来()
    fout << ch << endl;
    fout.close();
    return 0;
}123456789101112131415 1.文件模式:
在上面我们看到了fout.open()是将fout对象和文件绑定起来,那么会有以下情况出现:
- 文件不存在
- 文件存在,但是没有写权限
- 文件存在,权限也正确(不考虑成功)
而我们按照上面的方法则是,如果文件不存在,则创建文件。如果文件存在则是将原来的文件清空,重新写入。(警告:千万不要这样整,万一一不小心将原来文件给删除了,那就一手凉凉了)
这里就得提到了ios_base类定义了一个openmode类型,如下表:
| 常量 | 含义 | 
|---|---|
| ios_base::in | 打开文件,读取 | 
| ios_base::out | 打开文件,写入 | 
| ios_base::ate | 打开文件,移到文件尾 | 
| ios_base::app | 追加到文件尾 | 
| ios_base::trunc | 如果文件存在,则截断文件 | 
| ios_base::binary | 二进制文件 | 
而我们在上面的fout.open()其实是有三个参数的,第一个是文件的路径,第二个是打开文件的类型,第三个是权限。如果不写的话,会采用默认参数,就是ios_base::out|ios_base::trunc;也就是会覆盖掉之前文件内容的。
2.文件输出:
还是比较一下标准输入吧:
| 标准输入 | 文件输出 | 
|---|---|
| 包含头文件iostream类 | 包含头文件fstream类 | 
| 定义了istream类 | 定义了ifstream类 | 
| istream声明了一个cin对象 | ifstream声明了fin(一个或多个自己命名)对象 | 
| 必须指明命名空间std:: | 必须指明命名空间std:: | 
| 结合cin与运算符>>一起显示各种数据 | 需要将之前创建的对象和文件相关联起来(open方法) 也和标准输入一样和运算符>>搭配使用 | 
| 可以使用cin和get()方法读取一个字符,也可以使用getline()来读取一行字符 | 结合ifstream对象使用get()和getline()来读取字符 | 
| 通过cin和eof(),fail()来判断输入是否成功 | 可以结合ifstream对象和eof(),fail()来判断是否读取完文件内容 | 
| … | 使用完成后需要将对象close() | 
测试代码如下:
#include <iostream>
#include <fstream>
using namespace std;
int main(){
    //标准输入
    char ch;
    cin >> ch;
    cout << ch << endl;
    //文件输入
    ifstream fin("data.txt");//可以直接在声明中创建对象
    if(!fin.is_open()){
        printf("open error!\n");
        return -1;
    }
    while(fin.good()){
        fin >> ch;
        cout << ch ;
    }
    if(fin.eof()){
        printf("已经读到文件结尾了!\n");
    }else if(fin.fail()){
        printf("判断最后一次读取数据的时候是否遇到了类型不配的情况");
    }else{//fin.bad()
        printf("出现意外的问题,如文件受损或硬件故障,最后一次读取数据的时候发生了这样的问题\n");
    }
    fin.close();
    return 0;
} 1.流状态:
这里我们要提一下上面代码中我们使用的good(),fail(),eof(),bad().等函数是什么呢? 这就牵扯到了流状态检查的概念了
c++文件流类从ios_base类中继承了一个流状态成员,如前面指出的,该成员存储了流状态的信息。good(一切顺利),eof(到达文件结尾),fail(判断结尾是否有误),bad(I/O是否操作失败)。如果一切顺利,则流状态是0(没有消息就是好消息),其他状态都是通过比特位的1来记录的文件流类还继承了ios_base类的报告流状态的方法,可以通过检查流状态来判断是否成功
最后附上c++文件模式和c的区别:
| c++模式 | c模式 | 含义 | 
|---|---|---|
| ios_base::in | r | 打开文件,读取 | 
| ios_base::out | w | 打开文件,写入 | 
| ios_base::out-ios_base::trunc | w | 打开文件,写入,如果存在文件,则截短文件 | 
| ios_base::out-ios_base::app | a | 打开文件,追加到文件尾 | 
| ios_base::in-ios_base::out | r+ | 打开文件读写,在文件允许的位置写入 | 
| ios_base::in-ios_base::out-ios_base::trunc | w+ | 打开并写入,如果已存在,则截短文件 | 
| c++mode-ios_base::binary | cmodeb | c++mode和二进制模式打开 | 
| c++mode-ios_base::ate | cmode | 已指定模式打开,并且移动到文件尾 | 
