文件的概念
所谓文件,是指存储在外部介质上的数据集合,是一批逻辑上有联系的数据。这个数据集有一个名称,教授作文件名。
文件的种类
- 文本文件:所有数据都按照文本方式存储的文件,叫做文本文件。
- 二进制文件,所有数据都按照二进制方式存储的文件,称作二进制文件。 一般来说,二进制文件节省存储空间并且输入或输出的速度较快。
文件操作中缓冲区的概念
缓冲区是在打开文件时分配的,每当打开一个文件,系统就给该文件在内存中分配缓存区(默认是512字节),数据无论是从计算机输入到文件,还是从文件中读入到计算机,都要经过缓冲区。
文件类型指针
在库函数stdio.h中专门定义了一种结构体,取名叫FILE,定义如下:
typedef struct{
short level; /*缓冲区满或空的状态*/
unsigned flags; /*文件状态标志*/
char fd; /*文件描述字*/
unsigned char hold; /*如无缓冲区不读字符*/
short bsize; /*缓冲区大小*/
unsigned char *buffer /*缓冲区首地址*/
unsigned char *curp /*当前位置指针,指向正要读的字节*/
unsigned istemp;
unsigned token;
}FILE;
定义文件指针的一般形式为:
FILE *指针变量名;
例如FILE * fp
;表示定义了一个文件类型的指针变量fp,只要将一个文件类型的结构体变量的地址赋给fp,fp便指向该文件类型的结构体变量。可以利用fp实现对该文件的各种操作。
接下来是对于文件的打开关闭的操作。
使用fopen()函数打开数据文件
fopen()函数的调用方式:
fopen(文件名,文件使用方式);
通常是将fopen()函数的返回值赋予一个指向文件的指针变量。如:
FILE * fp;
fp=fopen(“al.txt”,“w”);
意义为打开当前目录下的文件al.txt,且只能进行“写”操作,并使fp指向该文件。
当然fopen函数还有很多种用法,如何去使用,还是要通过用户自己去设置,必须是编译系统知道三个信息:
- 需要打开的文件地址及名字;
- 对所打开文件需要进行什么操作;
- 使哪个文件类型指针去指向该文件。
关于打开文件再举一栗子:
FILE * fp;
fp=fopen(“d:\\study\\wo.txt”,“w”);
其意义是打开d磁盘驱动器的study目录下的文件wo.txt,对其进行只写操作。
关于对打开文件的操作列举:
文件使用方式 --------------- 含义
- r(只读): 打开一个已存在的文本文件,只能从中读取数据;
- w(只写):打开或新建一个文本文件,只能写入数据;若文件已存在则覆盖原全部文件;
- a(追加):打开已存在的文本文件,并在文件末尾写入数据;
- rb(只读):打开一个已存在的二进制文件,只能从中读取数据;
- wb(只写):打开或新建一个二进制文件,只能写入数据;若文件已存在则覆盖原全部内容;
- ab(追加):打开已存在的二进制文件,并在文件末尾写入数据;
- r+(读写):打开一个已存在的文本文件,允许读写数据,写入时只依次覆盖指针访问到的位置,不会覆盖全部内容;
- w+(读写):打开或新建一个文本文件,允许读写,若文件已存在,写入时覆盖文件全部内容;
- a+(读写):打开一个已存在的文本文件,可以读出数据也可以在文件末尾写入数据;
- rb+(读写):打开或新建一个二进制文件,允许读写,若文件已存在,写入时覆盖文件全部内容;
- rw+(读写):打开或新建一个二进制文件,允许读写,若文件已存在,写入时覆盖文件全部内容;
- ra+(读写):打开一个已存在的二进制文件,可以读出数据也可以在文件末尾写入数据;
说明
- 用“r”方式打开的文件只能用于向计算机输入而不能用作向该文件输出数据,而且该文件必须已经存在并存有数据,若打开一个不存在文件,则会报错。
- 用“w”方式打开的文件只能用于向该文件写数据(即输入到文件),而不能用来向计算机输入。如果原来不存在该文件,则在打开文件前新建立一个以指定的名字命名的文件。如果原来已存在一个以该文件名命名的文件,则在打开前先将该文件删去,然后重新建立一个新文件。
- 用“a”方式打开文件时,文件读写标记移到文件末尾。若文件不存在时,创建文件用于写入。
- 用“r+”“w+”“a+”方式打开的文件既可以用来输入数据,也可以用来输出数据。用“r+”方式时该文件应该已存在。用“w+”则新建一个文件,先向此文件写数据,然后可以读此文件中的数据。用“a+”则原来的文件不被删去,文件读写位置标记移到文件末尾,可以添加,也可以读。
- 如果打开失败,fopen()函数将会带回一个错误信息。fopen()函数将待会一个空指针值NULL。常用下面方法打开一个文件:
fp=fopen(“file”,“r”);
if(fp==NULL){
printf("cannot open this file\n");
exit(0);}
用fclose()函数关闭数据文件
在打开文件并完成一定的操作之后,必须要通过fclose()函数将其关闭,否则可能会造成数据丢失。
fclose()函数调用的一般形式:
fclose(文件指针);
例如:fclose(fp);
参数fp是当初打开文件时fopen()函数的返回值。函数执行成功返回0,否则返回-1。
当文件被成功关闭之后,其文件指针就不再指向人和文件了,当然可以重用,用于指向另一个文件。注意一个文件指针在某一时刻只能以一种方式打开一个文件。
文件的读写
- 字符读写函数:fgetc()和fputc()
- 字符串读写函数:fgets()和fputs()
- 格式化读写函数:fscanf()和fprintf()
- 数据块读写函数:fread()和fwrite()
注:
其中fread()和fwrite()函数可用于任何文件,其与函数只能用于文本文件。
fgetc():
从指定文件读入一个字符,该文件必须是以读或读写方式打开的。
调用形式:
字符变量=fgetc(文件指针);
fputc():
把一个字符写入到磁盘文件中。一般形式为:
fputc(字符,文件指针);
其中,字符可以使字符变量,也可以是字符常量。写数据成功后,同时将读写位置指针向前移动一个字节,及指向下一个写入位置。
fgets():
从指定文件读入一个字符串,该文件必须是以读或读写方式打开的。调用形式为:
fgets(str,n,fp);
其中n是要求得到的字符串个数,但实际上只读到n-1个字符,然后在最后加一个‘\0’字符,再作为整体放到字符串数组str中。执行fgets()成功,返回str数组首地址,如果一开始就遇到文件尾或读数据错误,返回NULL。
fputs():
把一个字符串写入到磁盘文件上。一般形式为:
fputs(str,fp);
功能为把字符串str写入到fp所指向的文件,fputs()函数中第一个参数可以是字符串常量,字符串数组名或字符型指针。字符串末尾的“\0”不输出,输出成功,函数值为0;失败,函数值为EOF。
fscanf():
调用格式为:
fscanf(fp,格式控制串,输入列表);
其中,fp是指向要读取文件的文件型指针,区别于scanf函数读写对象是键盘,fscanf函数读写对象是文件。
功能是从fp指向的文件中,按格式控制串中的控制符读取相应数据赋予输入列表中对应的变量。
栗子:fscanf(fp,"%d,%f",&a,&f);:其从指定的磁盘文件中读取ASCII字符,并按“%d”和“%f”格式转换成二进制形式的数据给变量a,f。
fprintf():
调用格式为:
fprintf(fp,格式控制串,输出列表);
其中,fp是指向要写入文件的文件型指针,区别于printf函数读写对象是显示器,fprintf函数读写对象是文件。
fread():
该函数用来从指定文件中读取一个指定字节的数据块。调用形式为:
fread(buffer,size,count,fp);
其中,buffer为读入数据在内存中存放的起始地址;size为每次要读取的字符数;count为要读取的次数;fp为文件类型指针。
功能是从文件中读count个字段,每个字段长度为size个字节,并把他们存放到buffer指针所指的缓冲器中。
栗子:fread(a,4,5,fp);:从fp所指的文件中,每次读4个字节即一个实数放到数组a中,连续读5次,即读5个实数到数组a中。
fwrite():
该函数用来将数据输出到磁盘文件上。调用形式为:
fwrite(buffer,size,count,fp);
功能是把buffer指针所指的缓冲器中,长度为size个字节和count个字段写到fp所指向的文件中去。
注意:用fread()和fwrite()函数按“记录”读写,所以必须用二进制方式打开文件。
我们还可以将文件位置指针定位到所要求读写的地方直读写,下面介绍两个可以实现这样功能的相关函数:
位置指针复位函数: rewind ()函数
在不关闭文件的情况下,回到文件头重新读写文件。调用形式为:
rewind(fp);
功能是使文件内部的位置指针指到文件的开头,此函数没有返回值。
随机读写函数: fseek()函数
调用形式:
fseek(fp,offset,fromwhere);
其中,fp是文件类型指针,offset为文件位置指针的位移量,指以起始位置为基准值顺着自动读写方向移动的字节数,它是一个长整型量,如果它的值为负数,表示逆着自动读写方向移动。fromwhere表示文件位置指针起始计算位置,其中fromwhere在stdio.h中定义如表:
········· 符号常数 — 数值 — 含义
- SEEK_SET — 0 — 从文件开头
- SEEK_CUR — 1 — 从当前位置
- SEEK_END — 2 — 从文件末尾
fseek函数作用是将文件的位置指针设置到从fromwhere开始的第offset字节的位置上,它一般用于对二进制文件进行操作。
栗子:fseek(fp,100L,0);:将位置指针移到离文件头100个字节处。
返回文件当前位置函数:
ftell()函数的作用是得到文件中位置指针的当前位置,调用形式为:
ftell(文件指针);
文件位置是以文件开始处到当前位置的位移量字节数表示,如果ftell()函数返回值为-1L,则表示出错。
参考文献:C原因程序设计(电子科技大学出版社)主编:钟志水 周鸣争