1、C/C+程序设计程序设计 C/C+程序设计程序设计第第9章章 文件文件操作操作 引言引言 文件是存储在外部介质上的数据集合。引入文件后,程序的输出结果可以转变为程序的输入数据,且能实现数据编辑和检索。第第9章章 文文 件件 操操 作作1文件的概念 所谓“文件”,一般指存储在外部存储介质(如磁盘、光盘等)上数据的集合。操作系统对文件的存取是按文件名进行的。之前曾接触过的文件有:源程序文件(.c)、目标文件(.obj)、可执行文件(.exe)、库文件(.h),本章所说的文件指数据文件。数据文件。9.1.1 文件的概念与分类文件的概念与分类9.1 文件概述文件概述2文件的分类文件的分类 普通文件普通
2、文件是指驻留在磁盘或其它外部介质上的有序数据集合,即磁盘上的文件。设备文件设备文件是指与主机相连的各种外部设备,如显示器、打印机、键盘等。通常把显示器显示器定义为标准输出文件标准输出文件(stdout),),把键盘键盘定义为标准输入文件(标准输入文件(stdin)。)。9.1 文件概述文件概述划划 分分 角角 度度分分 类类从用户角度从用户角度普通文件普通文件设备文件设备文件从存储形式从存储形式ASCII码文件码文件二进制文件二进制文件从文件内容从文件内容程序文件程序文件数据文件数据文件字字 符:符:1234ASCII码:码:0011 0001 0011 0010 0011 0011 0011
3、 0100 共需要共需要 4 个字节个字节在显示器上按字符显示,可读懂在显示器上按字符显示,可读懂文本文件文本文件:也称ASCII文件,它是把数据转换成对应的ASCII码值,存放在磁盘上,每个字符占1个字节。二进制文件二进制文件:将数据以二进制形式存放到磁盘上。例如,短整型数据1234,在二进制文件中,占用2个字节;而在文本文件中,则需占用4个字节,如下图所示:程序文件程序文件:程序的源代码形成的文件;数据文件数据文件:程序需要使用的数据保存在磁盘上时形成的文件。9.1 文件概述文件概述3缓冲文件系统和非缓冲文件系统 缓冲文件系统:缓冲文件系统:系统自动在内存中为每一个正在使用的文件开辟一个缓
4、冲区,作为程序与文件之间数据交换的中间媒介。即:C程序读写文件经过缓冲区进行。缓冲文件系统利用文件指针文件指针标识文件。内存 外存缓冲区缓冲区 C程序9.1 文件概述文件概述文件指针定义:文件指针定义:FILE *指针变量指针变量;例:FILE *fp;9.1 文件概述文件概述含有文件信息的结构体类型,在stdio.h中定义说明:只要把某个文件的FILE型变量地址赋给fp,就表明在这个文件和fp之间建立起了联系,C语言就把这个指针作为该文件的标识,在程序中就可以通过fp来访问这个文件。9.1.2 文件的操作方式文件的操作方式1.数据文件的操作步骤C语言中对文件的3个主要操作:(1)打开文件)打
5、开文件:用标准库函数fopen()以某种操作方式打开磁盘上指定的文件。(2)读/写文件:用文件输入、输出函数对文件进行读写操作。(3)关闭文件:用标准库函数fclose()将文件关闭。关闭文件主要完成以下工作:关闭文件缓冲区,将缓冲区中还没有输出的数据输出到磁盘文件中,以保证数据不丢失;切断文件指针与文件名之间的联系,释放文件指针。“读读”或输入:或输入:磁盘上文件 内存 “写写”或或输出输出:内存 磁盘文件9.1 文件概述文件概述2.数据文件操作方式数据文件操作方式二进制文件打开二进制文件打开方式同一表,只是在方式字符后加方式同一表,只是在方式字符后加b(1 1)文件打开函数文件打开函数 f
6、openfopen()()3.数据文件的打开与关闭数据文件的打开与关闭fopen函数函数调用调用格式:格式:fopen(文件名文件名,文件操作方式文件操作方式)功能功能:使程序与文件之间建立关联。成功,返回一个FILE类型的指针值;若不成功,则返回一个空指针值NULL。说明:说明:1)“文件名”是包含路径的一个文件名,用西文双引号括起来。若文件与程序路径相同,可省略路径。2)“文件操作方式”是指以何种方式对文件进行操作。9.1 文件概述文件概述9.1 文件概述文件概述(2)数据文件的关闭函数)数据文件的关闭函数fclose()fclose函数的一般格式如下:fclose(文件指针名文件指针名)
7、;功能:功能:关闭文件指针指向的文件。如果文件关闭成功,函数返回0值,如果关闭失败,函数返回EOF(-1)。通常在程序中会检测文件是否正常打开。常用下面的程序段来打开一个文件,并检查是否打开成功。FILE *fp;if(fp=fopen(“d:c_c+data.txt”,“r”)=NULL)printf(file can not open!n);exit(0);(文件打开成功后的语句)9.2 文件的读写操作文件的读写操作9.2.1 字符读字符读/写函数写函数1.写字符函数写字符函数fputc()fputc函数的一般格式:fputc(ch,fp);功能:功能:将ch代表的字符输出到fp所指向的文
8、件中。成功返回刚写入的字符;否则返回EOF(-1)值。例如:fputc(A,fp);/将字符 A 写入 fp 指向的文件中 2.读字符函数读字符函数fgetc()fgetc函数的一般格式如下:ch=fgetc(fp);功能:功能:从fp所指的文本文件中读取一个字符,并赋给字符型变量ch。成功返回读出的字符;如果读到文件结束符或出错,则返回EOF(-1)值。9.2 文件的读写操作文件的读写操作【例例9-1】将键盘输入的一串字符(以输入的回车符为结束标志)以单个字符形式写入L9-1.txt文件中,再将文件内容以单个字符形式从该文件中读出并显示到屏幕上。#include#include void r
9、eadchar()FILE *fp;char ch;if(fp=fopen(L9-1.txt,r)=NULL)printf(file can not open!n);return;ch=fgetc(fp);while(ch!=EOF)/只要文件没有结束,则重复执行以下操作 putchar(ch);/将当前读取的字符显示到屏幕ch=fgetc(fp);/继续读取下一个字符 fclose(fp);9.2 文件的读写操作文件的读写操作void writechar()FILE *fp;char ch;if(fp=fopen(L9-1.txt,w)=NULL)printf(file can not op
10、en!n);return;ch=getchar();while(ch!=n)/只要输入的不是回车符,则重复执行以下操作 fputc(ch,fp);/向指定的文件中写入刚输入的字符ch=getchar();/继续输入下一个字符 fclose(fp);void main()writechar();readchar();printf(n);9.2 文件的读写操作文件的读写操作9.2.2 字符串读字符串读/写函数写函数1.写字符串函数写字符串函数fputs()fputs函数的一般格式如下:fputs(str,fp);功能:功能:将str代表的字符串写入fp指向的文件中,字符串末尾的“0”不予写入。正确
11、返回写入的字符个数,文件内部指针会自动后移到新的写入位置;错误则返回EOF(-1)值。2.读字符串函数读字符串函数fgets()fgets函数的一般格式如下:fgets(str,n,fp);功能:功能:从fp所指向的文件中读取不超过n-1个的字符,存到str中,并在末尾加 0。成功返回读取的字符串,否则返回NULL。9.2 文件的读写操作文件的读写操作说明:说明:1)n是要读出的字符串的所占的最大字节数,0占一个字节,故最多可读取n-1个字符。2)在读满n-1个字符前,若遇回车换行符(若遇回车换行符(n),),则读出这个回车换行符,结束读操作,并在字符串末尾后加 0,函数正常返回。这时文件读写
12、指针已经移到这个回车换行符后面。3)在读满n-1个字符前,若遇文件结束标志,直接加0,结束读操作,函数正常返回。4)在读满n-1个字符前,如果遇回车符(如果遇回车符(r),则读出该字符,而继续读取的下一个字符会存放在str指向的内存区域的第1个位置,直到遇到n或者遇文件结束或者读满n-1个字符为止,字符串末尾后加0。9.2 文件的读写操作文件的读写操作【例例9-2】下列程序的功能是将字符串Beijingr123456n&*以字符串方式写入文件“L9-2.txt”,再以字符方式读出。试分析运行结果。#include#include#include int main()FILE *fp;char
13、str140=abcdefgr132456n&*,str240;if(fp=fopen(L9-2.txt,w)=NULL)printf(file can not open!n);exit(0);fputs(str1,fp);/写字符串到文件 fclose(fp);9.2 文件的读写操作文件的读写操作 if(fp=fopen(L9-2.txt,r)=NULL)printf(file can not open!n);exit(0);fgets(str2,12,fp);/读字符串到str2数组中,最多读11个字符 puts(str2);/输出字符串到屏幕 printf(本次读取的字符串长度为:%dn
14、,strlen(str2);fgets(str2,14,fp);/读字符串到str2数组中,最多读13个字符puts(str2);fgets(str2,10,fp);/继续读取不超过10个字符的字符串puts(str2);printf(本次读取的字符串长度为:%dn,strlen(str2);fclose(fp);return 0;运行结果:运行结果:123defg 本次读取的字符串长度为:本次读取的字符串长度为:11456&*本次读取的字符串长度为:本次读取的字符串长度为:6结果分析:结果分析:【例例9-3】将字符串Beijing、Shanghai、Xian、Dalian 写入文件“L9-3
15、.txt”中,然后再从文件中读出来,并显示在屏幕上。分析:在向文件写入一个字符串时,其结束标志0 并不写入,如果连续将多个字符串写入文件,读出时就无法判断一个字符串的结束位置。因此,写入一个字符串后需要再写入一个n,在读出时遇n 则自动替换成0,从而正确读出一个字符串。#include#include void main()FILE *fp;int i;char str1410=Beijing,Shanghai,Xian,Dalian,str2410;if(fp=fopen(L9-3.txt,w)=NULL)printf(file can not open!n);exit(0);for(i=0
16、;i 4;i+)fputs(str1 i ,fp);/写字符串到文件 fputs(“n”,fp);/写完一个字符串后,再写一个换行符,想想为什么?fclose(fp);if(fp=fopen(L9-3.txt,r)=NULL)printf(file can not open!n);exit(0);for(i=0;i 4;i+)fgets(str2 i ,10,fp);/读字符串,每次最多读10个字符 fclose(fp);for(i=0;i 4;i+)/输出字符串到屏幕 printf(%s,str2 i );9.2.3 数据块读数据块读/写函数写函数指一次性地将一个或若干个指定长度的数据块写入
17、文件或从文件中读出的函数。1.写数据块函数写数据块函数fwrite()fwrite函数的格式如下:fwrite(buf,size,n,fp);功能:功能:将内存从buf开始的n个大小为size个字节的数据块写入fp所指向的文件中。成功返回实际写入的数据块的个数,否则返回NULL。说明:说明:buf为内存中写入数据的首地址;size为每个数据块的大小;n为数据块的个数;fp为文件指针。写入的信息全部按二进写入的信息全部按二进制存放制存放。例如:fwrite(buf,2,18,fp);注意:注意:用块方式写入的数据,以文本方式打开时,信息因二进制而显示乱码!2.读数据块函数读数据块函数fread(
18、)fread函数的格式如下:fread(buf,size,n,fp);功能:功能:从fp所指向的文件中,一次读取n个大小为size的数据块,存放到buf所指向的内存中。如果操作成功,返回读取的数据块的个数,否则返回0。说明:说明:buf为将要存放数据的内存首地址,size为每个数据块的大小,n为数据块的个数,fp为文件指针。【例例9-4】用函数fwrite()把数组中的10个数据写入文件“L9-4.txt”中,然后再用函数fread()读出并显示在屏幕上。#include#include void main()FILE *fp;int a10=1,2,3,4,5,6,7,8,9,10 ,b10
19、,i;if(fp=fopen(L9-4.txt,w)=NULL)printf(file can not open!n);exit(0);fwrite(a,sizeof(int),10,fp);/以二进制形式存放 fclose(fp);if(fp=fopen(L9-4.txt,r)=NULL)printf(file can not open!n);exit(0);fread(b,sizeof(int),10,fp);/读数据到数组b fclose(fp);for(i=0;i 10;i+)/输出数据到屏幕 printf(%5d ,b i );9.2.4 格式读格式读/写函数写函数格式读函数fsca
20、nf()和格式写函数fprintf()是按指定格式对文件进行读、写操作的常用函数。它们与格式输入函数scanf()和格式输出函数printf()相对应,不同的是scanf()和printf()的读写对象是标准输入输出设备,而fscanf()和fprintf()的读写对象是磁盘文件。1.格式写函数格式写函数fprintf()fprintf函数的一般格式如下:fprintf(文件指针文件指针,);功能:按指定的格式将输出项写入由文件指针指向的文件中。成功返回写入文件的数据个数,否则返回EOF(-1)。说明:“格式控制字符串”和“输出变量列表”的含义,与格式输出函数printf()完全一样。写入的信
21、息全部按写入的信息全部按ASCII码码值存放。值存放。2.格式读函数格式读函数fscanf()fscanf函数的一般格式如下:fscanf(文件指针文件指针,);功能:功能:从文件中,按“格式控制字符串”指定的格式读取数据,输入到“输入地址列表”所列出的变量地址中。若读取正确,返回实际读取的数据个数;若没有读到数据项,返回0;若文件结束,则返回EOF。说明:说明:使用fprintf()和fscanf()时,要保证格式描述符与数据类型的一致性,否则会出错。通常应该是按什么格式写入数据,再按什么格式读出数据。【例例9-5】利用格式读写函数,将整数24、实数12.34、字符串“hello”写到“L9
22、-5.txt”文件中,然后再读出并显示在屏幕上。#include#include int main()FILE *fp;int a1=24,a2;float f1=12.34F,f2;char c1 =hello,c210;if(fp=fopen(L9-5.txt,w)=NULL)printf(file can not open!n);exit(0);fprintf(fp,%d%f%s,a1,f1,c1);/写数据到文件fp中 fclose(fp);if(fp=fopen(L9-5.txt,r)=NULL)printf(file can not open!n);exit(0);fscanf(f
23、p,%d%f%s,&a2,&f2,c2);/从fp中读数据到内存变量中 fclose(fp);printf(n%d%f%s ,a2,f2,c2);return 0;9.3 文件操作的其他函数文件操作的其他函数1.文件尾测试函数文件尾测试函数feof()feof函数的一般格式函数的一般格式:feof(fp);功能:功能:测试fp所指向的文件指针是否遇到文件结束标志。如果是返回非0值,否则返回0值。通常,feof(fp)为0时才可对文件进行读操作,若为非0则应该结束读操作。2.错误测试函数错误测试函数ferror()ferror函数的一般格式如下:函数的一般格式如下:ferror(fp);功能:功
24、能:对文件最近一次的操作进行正确性测试。如果操作出错,返回非0值,否则返回0值。3.文件头定位函数文件头定位函数rewind()rewind函数的一般格式如下:函数的一般格式如下:rewind(fp);功能:功能:使文件的内部读写指针移动到文件的头。函数无返回值。4.返回文件当前读写位置函数返回文件当前读写位置函数ftell()ftell函数的一般格式如下:函数的一般格式如下:ftell(fp);功能:功能:返回文件指针的当前读写位置值。调用正确,返回文件指针的当前位置,返回值为长整型数,是相对于文件头的字节数;出错时,返回-1L。5.文件随机定位函数文件随机定位函数fseek()fseek函
25、数的一般格式如下函数的一般格式如下:fseek(fp,位移量位移量,起始位置起始位置);功能:功能:将fp指向的文件指针从指定的“起始位置”移动一个指定的“位移量”。移动成功,返回0;否则返回非0。其中,“起始位置”指定文件定位的起始基点。“位移量”指明从起始基点开始移动的字节数,它是一个长整型,值为正时,表示向文件尾的方向移动;值为负时,表示向文件头的方向移动。符符 号号 常常 数数值值含含 义义SEEK_SET0文件头文件头SEEK_CUR1文件内部指针当前位置文件内部指针当前位置SEEK_ END2文件尾文件尾起始位置参数取值表【例例9-6】将字符串“We are studying language C.”写入文件“L9-6.txt”中,然后再从文件中读出所有字符,显示在屏幕上。【例例9-7】若有文件“L9-7.txt”,存放了下列结构体类型的数据10个,试从该文件中取出第2个记录并输出。程序如下: