C++ (fstream、ifstream、ofstream) 文件流读、写、状态、指针操作分析

C++ (fstream、istream、ostream) 文件读写操作分析

最近正再一次学习C++,因此记录一些学习过程的总结。

1
2
3
4
5
//
#include <fstream> //既有读也有写
ifstream //读 文件读操作,存储设备读区到内存中  
ofstream //写 文件写操作 内存写入存储设备
//ifstream:定义要用于从文件中按顺序读取单字节字符数据的流.

(一)、打开文件

打开文件的方法有两种:

1、在声名时,利用添加的文件名打开文件。

1
2
fstream _file("text.txt");//这行语句会打开文件
fstream _file1;//这行不会打开任何文件

2、在fstream类中,成员函数open()实现打开文件的操作,从而将数据流和文件进行关联,通过ofstream,ifstream,fstream对象进行对文件的读写操作。
实际上,第一种方法即在声名时调用了open()方法

源码如下
在这里插入图片描述

(二)open()函数

源码:
在这里插入图片描述
__s:是文件名
__mode是打开文件的模式

文件名可以是绝对路径也可以是相对路径
相对路径的话即在该cpp文件所在的目录下的某文件。
绝对路径即是特指位置的文件。

mode有很多种方式:
如:
ios::in 为输入(读)而打开文件
ios::out 为输出(写)而打开文件
ios::ate 初始位置:文件尾
ios::app 所有输出附加在文件末尾
ios::trunc 如果文件已存在则先删除该文件
ios::binary 二进制方式

上述方式可以自行组合,利用或运算分割

例如:以二进制,即读取也写入的方式 打开相对路径下的文件text.txt

1
2
//以二进制,即读取也写入的方式 打开相对路径下的文件text.txt
fstream _file("text.txt",ios::in | ios::out | ios::binary);

函数is_open()用于判读该文件是否打开,比较简单,不做赘述。

(三)close() 关闭文件

当文件读写操作完成之后,必须将文件关闭以使文件重新变为可访问的。
fstream成员函数close(),它负责将缓存中的数据排放出来并关闭文件。这个函数一旦被调用,原先的流对象就可以被用来打开其它的文件了,这个文件也就可以重新被其它的进程所访问了。

源码:
在这里插入图片描述

为防止流对象被销毁时还联系着打开的文件,析构函数将会自动调用关闭函数close。

源码
在这里插入图片描述

(四)文件的读写

文件的读:
利用字符数组做buff

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//以二进制,即读取也写入的方式 打开相对路径下的文件text.txt
#include <fstream>
#include <iostream>
using namespace std;
int main(){<!-- -->
    char buff[256];
    fstream _file("text.txt");
    if(_file.is_open()){<!-- -->
        while( !_file.eof()){<!-- -->            _file.getline(buff,200);
            cout<<buff<<endl;
        }
    }else{<!-- -->
        perror("error in file");
    }
    _file.close();
    system("pause");
    return 0;
}

输出:

在这里插入图片描述
文件的写:

1.使用 write() 函数
第一个参数是要写入的数据,第二个参数是数据的大小。

1
2
3
4
5
6
7
8
9
10
#include <fstream>
#include <iostream>
using namespace std;
int main(){<!-- -->
    fstream _file("text.txt");
    _file.write("aaaaaaaaaaaaaa",14);
    _file.close();
    system("pause");
    return 0;
}

结果:
在这里插入图片描述
源码:
在这里插入图片描述

2.使用重载<< >>
在这里插入图片描述
输出:
在这里插入图片描述

注意:这里在用open打开时,添加ios::app模式,会将输出到文件的数据以追加方式输出到该文件。不加app模式会直接覆盖原文件数据输出。
在这里插入图片描述
输出:
在这里插入图片描述

(五)状态标志符

一些验证文件流的状态的成员函数(所有都返回bool型返回值):

bad()
如果在读写过程中出错,返回 true 。例如:当我们要对一个不是打开为写状态的文件进行写入时,或者我们要写入的设备没有剩余空间的时候。

fail()
除了与bad() 同样的情况下会返回 true 以外,加上格式错误时也返回true ,例如当想要读入一个整数,而获得了一个字母的时候。

eof()
如果读文件到达文件末尾,返回true。

good()
这是最通用的:如果调用以上任何一个函数返回true 的话,此函数返回 false 。

要想重置以上成员函数所检查的状态标志,可以使用成员函数clear()。

(六)文件流的指针操作

tellg() 和 tellp()
这两个成员函数不用传入参数,返回pos_type 类型的值(根据ANSI-C++ 标准) ,就是一个整数,代表当前get 流指针的位置 (用tellg) 或 put 流指针的位置(用tellp).

源码:可以进去看看混个脸熟
在这里插入图片描述
tellg()函数不需要带参数,它返回当前定位指针的位置,也代表着输入流的大小。

seekg() 和seekp()
这对函数分别用来改变流指针get 和put的位置。两个函数都被重载为两种不同的原型:

seekg ( pos_type position );
seekp ( pos_type position );
使用这个原型,流指针被改变为指向从文件开始计算的一个绝对位置。要求传入的参数类型与函数 tellg 和tellp 的返回值类型相同。

seekg ( off_type offset, seekdir direction );
seekp ( off_type offset, seekdir direction );
使用这个原型可以指定由参数direction决定的一个具体的指针开始计算的一个位移(offset)。它可以是:

ios::beg 从流开始位置计算的位移
ios::cur 从流指针当前位置开始计算的位移
ios::end 从流末尾处开始计算的位移

流指针 get 和 put 的值对文本文件(text file)和二进制文件(binary file)的计算方法都是不同的,因为文本模式的文件中某些特殊字符可能被修改。由于这个原因,建议对以文本文件模式打开的文件总是使用seekg 和 seekp的第一种原型,而且不要对tellg 或 tellp 的返回值进行修改。

例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <fstream>
#include <iostream>
using namespace std;
int main(){<!-- -->
    long st=0,end=0;
    fstream _file("text.txt");
    st=_file.tellg();
    _file.seekg(0,ios::end);
    end=_file.tellg();
    _file.close();
    cout<<"the file's size is "<<(end-st)<<endl;
    system("pause");
    return 0;
}

在这里插入图片描述

以上是基本的文件流操作