对文件数据的读写可以分为顺序读写和随机读写。
顺序读写
即挨着顺序对文件中的数据进行输入或输出
如果我们要读写一个文件,就必须先打开这个文件,读写完后,还需要关闭这个文件。这就像,你要喝一杯水,需要先打开杯盖,才能喝水,喝完水后还需要把盖子盖上。
打开文件的原理是,打开文件后,在内存中创建一个FILE类型的变量,用来记录打开的文件的相关信息。FILE类型是一个结构体类型。
关闭文件的原理是,根据这个FILE类型的变量里描述的文件信息,通过一定手段把文件关闭。
在学习C语言的过程中,我们不需要知道具体的细节,会用就行了。C语言中打开文件需要使用函数fopen,关闭文件需要使用函数fclose。
fopen的声明如下:
FILE * fopen ( const char * filename, const char * mode );
看这个声明,可以了解到,第一个参数就是要打开文件的文件名,第二个参数是用什么方式打开(读?写?还是其他模式?)。函数会打开这个文件,在内存中创建一个相对应的文件信息区,其实就是创建一个FILE类型的变量,这个变量记录了文件的相关信息。接着,这个函数会返回这个FILE变量的地址,如果函数打开文件失败会返回NULL指针。
文件的随机读写
事实上,当我们顺序读写文件时,文件中会有一个指针记录你读(或者写)到哪了。比如,一个文件里存着"abcdefg",当我们打开文件时,这个指针默认指向了第一个字符a,当你用fgetc读完a后,这个指针就指向了下一个字符b,当你再使用fgetc读取文件时就读到了b,以此类推。如果我们想一上来就读e,除了按照顺序读写的方法,把前面的abcd全都读走,还有一种方法,直接让这个指针指向e,就可以了。
我们使用fopen打开一个文件可以得到一个文件指针,这个文件指针也会被用于读写文件的时候。
所以,文件的随机读写,本质上是改变记录读写位置的指针的指向,就能够读写任意位置了。下面我们将学习与此相关的3个函数,分别是:
1.fseek,改变该指针的指向。
2.ftell,获取该指针相对于起始位置的偏移量。
3.rewind,使文件指针指向起始位置。
注意事项
1.文件的随机读写本质上是改变一个指向文件读写位置的指针的指向。
2.使用fseek和rewind函数可以做到(1)这一点。其中,fseek需要知道该指针需要指向的新的位置,具体需要一个相对于某起始位置(origin)的偏移量(offset),其中origin可以取值为SEEK_SET(文件的起始位置),SEEK_END(文件的结束位置)和SEEK_CUR(当前位置)。rewind函数会让该指针直接指向SEEK_SET,所以rewind(pf);等价于fseek(pf, 0, SEEK_SET);。
3.使用ftell函数可以获取当前该指针相对于起始位置的偏移量。
什么是二进制文件
数据在内存中以二进制的形式存储,如果不加转换的输出到外存(磁盘),就是二进制文件!
二进制文件是按二进制的编码方式来存放文件的。 例如, 数10000的存储形式为:0010 0111 0001 0000只占二个字节。二进制文件虽然也可在屏幕上显示,但其内容无法读懂。具体这个是什么,是根据文本编码显示的符号,其本身还是二进制,不需要深究!
无论是文本文件还是二进制文件,其本质都是二进制存储。
3.文本文件和二进制文件的字节存储
文本文件的字节存储
假定:还是将10000这个数以ASCII码的形式存储在文件中
二进制文件的字节存储
数据在内存中以二进制的形式存储,不加转换的输出到外存(磁盘)!
1)fread
fread(buffer,size,count,fp)
buffer:指针,表示内存中存储空间的首地址;
count:要读写的单元数
size:每单元的字节数
fp:文件指针。
从fp所指的文件中读count个单元,每个单元size个字节,到以buffer为起始地址的内存中
2)fwrite
fwrite(buffer,size,count,fp)
buffer:指针,表示内存中存储空间的首地址;
count:要读写的单元数
size:每单元的字节数
fp:文件指针。
将以buffer为起始地址内存中的count个单元,每个单元size个字节写到fp所指的文件中。
文件的读取结束和判定
1、feof、ferror 函数返回值
(1) feof 函数
(2) ferror 函数
2、feof、ferror 函数函数使用
fgetc、fgets的返回值说明都有提到一句话 “调用失败或者文件读取结束时,函数返回EOF”。但是光凭EOF我们也无从知晓,是调用失败还是文件读取结束。
因此,C语言给我们提供了 feof、ferror 函数。这两个函数 一般可以配套使用,一个用来是否读取到文件尾,一个用来判断是否遇到错误(调用失败)。
feof:当文件读取结束时,判断是不是遇到文件末尾才结束的
ferror:当文件读取结束时,判断是不是遇到错误才读取结束的
什么是文件缓冲区
每一个正在使用的文件,操作系统都会为其在内存中开辟一块区域,称之为:文件缓冲区。每当我们想从内存向硬盘中输出数据,都会先将数据输送到缓冲区中,然后装满缓冲区后才一起输送到硬盘上。如果想从硬盘向计算机内读入数据,则会先将读到的数据输送到缓冲区中,装满缓冲区后再逐个将数据输送到程序数据区(内存中的变量)。
因为有缓冲区的存在,C语言在操作文件的时候,需要做刷新缓冲区或者在文件操作结束的时候关闭文件。 如果不做,可能导致读写文件的问题。