1、本章要点p 文件的概念,文件的概念,C文件是如何存储的?文件是如何存储的?p 文本文件和二进制文件的概念;文本文件和二进制文件的概念;p 怎样打开、关闭文件?怎样打开、关闭文件?p 怎样编写文件读写程序?怎样编写文件读写程序?p 怎样编写程序,实现简单的数据处理?怎样编写程序,实现简单的数据处理?9.1 9.1 将将“Hello World”Hello World”写入到文件写入到文件例例9-1 把短句把短句“Hello World!”保存到磁保存到磁盘文件盘文件f1.txt中。中。#include#include int main(void)FILE*fp;/*定义文件指针定义文件指针*/i
2、f(fp=fopen(f1.txt,w)=NULL)/*打开文件打开文件*/printf(File open error!n);exit(0);fputs(Hello World!,fp);/*写文件写文件*/if(fclose(fp)/*关闭文件关闭文件*/printf(Can not close the file!n);exit(0);return 0;例9-1 源程序9.1.2 文件的概念u文件:保存在外存储器上的一组数据的有序集合文件:保存在外存储器上的一组数据的有序集合u特点特点:数据数据长久保存长久保存 数据数据长度不定长度不定 数据按数据按顺序存取顺序存取9.1.3 文本文件和二
3、进制文件 语言中的文件是数据流语言中的文件是数据流文件的两种数据形式:文件的两种数据形式:l ASCII码码(文本文件(文本文件 text stream)字符流字符流l 二进制码二进制码(二进制文件(二进制文件 binary stream)二进制文件是直接把内存数据以二进制形式保存。二进制文件是直接把内存数据以二进制形式保存。例如,整数例如,整数1234l文本文件保存:文本文件保存:49 50 51 52(4个字符)个字符)l二进制文件保存:二进制文件保存:04D2(1234的二进制数)的二进制数)9.1.4 缓冲文件系统 内存单元内存单元 内存单元内存单元数据数据 缓冲器缓冲器512字节字节
4、文件文件由操作由操作系统自系统自动完成动完成程序控制程序控制由于磁盘速度慢由于磁盘速度慢直接把数据写到磁盘效率很低直接把数据写到磁盘效率很低9.1.4 缓冲文件系统l 向磁盘输出数据:数据向磁盘输出数据:数据 缓冲区,装缓冲区,装满缓冲区后满缓冲区后 磁盘文件。磁盘文件。l 从磁盘读入数据:先从磁盘读入数据:先一次性一次性从磁盘文件将从磁盘文件将一批一批数据输入数据输入到缓冲区,然后再从缓冲区到缓冲区,然后再从缓冲区逐个逐个读入读入数据到变量数据到变量。数据数据 缓冲器缓冲器512字节字节文件文件由操作由操作系统自系统自动完成动完成程序控制程序控制文件名文件名 内存单元内存单元 内存单元内存单
5、元用什么标识用什么标识缓冲文件与文件类型指针用文件指针指示文件缓冲区中具体读写的位置用文件指针指示文件缓冲区中具体读写的位置FILE *fp;数据数据缓冲器缓冲器512字节字节文件文件由操作由操作系统自系统自动完成动完成程序控制程序控制fp同时使用多个文件时,每个文件都有缓冲区,用同时使用多个文件时,每个文件都有缓冲区,用不同的文件指针分别指示。不同的文件指针分别指示。9.1.5 文件结构与文件类型指针1.自定义类型(自定义类型(typedef):):l 将将C语言中的已有类型(包括已定义过的自定语言中的已有类型(包括已定义过的自定义类型)重新命名义类型)重新命名l 新的名称可以代替已有数据类
6、型新的名称可以代替已有数据类型l 常用于简化对复杂数据类型定义的描述常用于简化对复杂数据类型定义的描述typedef ;自定义类型(typedef)typedef ;int i,j;INTEGER i,j;int*p1;POINT p1;自定义类型(typedef)的使用方法l 定义变量定义变量 int il 变量名变量名新类型名新类型名 int INTEGERl 加上加上 typedef typedef int INTEGERl 用新类型名定义变量用新类型名定义变量 INTEGER i;int num10int NUM10typedef int NUM10NUM a int a10typed
7、ef struct short level;/*缓冲区使用量缓冲区使用量 */unsigned flags;/*文件状态标志文件状态标志*/char fd;/*文件描述符文件描述符*/short bsize;/*缓冲区大小缓冲区大小*/unsigned char *buffer;/*文件缓冲区的首地址文件缓冲区的首地址*/unsigned char *curp;/*指向文件缓冲区的工作指指向文件缓冲区的工作指针针*/unsigned char hold;/*其他信息其他信息*/unsigned istemp;short token;FILE;2.文件结构FILE3.文件类型指针FILE*fp指
8、向文件缓冲区,通过移动指针实现对文件的操作指向文件缓冲区,通过移动指针实现对文件的操作数据数据缓冲器缓冲器512字节字节文件文件由操作由操作系统自系统自动完成动完成程序控制程序控制fp同时使用多个文件时,每个文件都有缓冲区,用同时使用多个文件时,每个文件都有缓冲区,用不同的文件指针分别指示。不同的文件指针分别指示。如何使如何使fp与具体与具体文件文件挂钩挂钩?9.2 读取学生成绩文件例例9-2 已知一个数据文件已知一个数据文件f.txt中保存了中保存了5个学生的计算机个学生的计算机等级考试成绩,包括学号、姓名和分数,文件内容如下等级考试成绩,包括学号、姓名和分数,文件内容如下,请将文件的内容读
9、出并显示到屏幕中。请将文件的内容读出并显示到屏幕中。301101 张文 91301102 陈慧 85301103 王卫东76301104 郑伟 69301105 郭温涛 55程序解析#include stdio.hint main(void)FILE*fp;/*定义文件指针定义文件指针*/long num;char stname20;int score;if(fp=fopen(f.txt,r)=NULL)/*打开文件打开文件 */printf(File open error!n);exit(0);while(!feof(fp)fscanf(fp,%ld%s%d,&num,stname,&sco
10、re);printf(%ld%s%dn,num,stname,score);if(fclose(fp)/*关闭文件关闭文件 */printf(Can not close the file!n);exit(0);打开文件if(fp=fopen(f.txt,r)=NULL)printf(File open error!n);exit(0);fopen(文件名文件名,文件打开方式文件打开方式)l使文件指针与相应文件实体对应起来使文件指针与相应文件实体对应起来l程序对文件指针进行操作,即程序对文件指针进行操作,即fp代表磁盘文件代表磁盘文件n 函数函数fopen()的返回值的返回值l执行成功,则返回包
11、含文件缓冲区等信息的执行成功,则返回包含文件缓冲区等信息的FILE型型地址地址,赋给文件,赋给文件指针指针fpl不成功,则返回一个不成功,则返回一个NULL(空值)(空值)exit(0):关闭所有打开的文件,并终止程序的执行关闭所有打开的文件,并终止程序的执行参数0表示程序正常结束;非0参数通常表示不正常的程序结束文件打开方式fp=fopen(f.txt,r)文件打开方式参数表文件打开方式参数表文件读写与打开方式if 读文件读文件 指定的文件必须存在,否则出错;指定的文件必须存在,否则出错;if 写文件写文件(指定的文件可以存在,也可以不存在指定的文件可以存在,也可以不存在)if 以以 w 方
12、式写方式写 if 该文件已经存在该文件已经存在 原文件将被删去重新建立;原文件将被删去重新建立;else 按指定的名字新建一个文件;按指定的名字新建一个文件;else if 以以 a 方式写方式写 if 该文件已经存在该文件已经存在 写入的数据将被添加到指定文件原有数据的后面,不会删去原来的内容;写入的数据将被添加到指定文件原有数据的后面,不会删去原来的内容;else 按指定的名字新建一个文件(与按指定的名字新建一个文件(与“w”相同);相同);if 文件同时读和写文件同时读和写 使用使用 r+、w+或或 a+打开文件打开文件 9.2.3 关闭文件if(fclose(fp)printf(Can
13、 not close the file!n);exit(0);fclose(文件指针文件指针)l把缓冲区中的数据写入磁盘扇区,确保写文件的正常完成把缓冲区中的数据写入磁盘扇区,确保写文件的正常完成l释放文件缓冲区单元和释放文件缓冲区单元和FILE结构体,使文件指针与具体文件脱钩。结构体,使文件指针与具体文件脱钩。函数函数fclose()的返回值的返回值l返回返回0:正常关闭文件:正常关闭文件l返回非返回非0:无法正常关闭文件:无法正常关闭文件9.3 文件复制例例9-3 已知一个文本数据文件已知一个文本数据文件f1.txt,请将,请将该文件复制一份,保存为该文件复制一份,保存为f2.txt。新建
14、一个文本文件新建一个文本文件f1.txt,将该文件与源程序放,将该文件与源程序放在同一目录下,执行程序,观察结果。在同一目录下,执行程序,观察结果。例12-3 源程序#include int main(void)FILE*fp1,*fp2;char c;if(fp1=fopen(f1.dat,r)=NULL)printf(File open error!n);exit(0);if(fp2=fopen(f2.dat,w)=NULL)printf(File open error!n);exit(0);while(!feof(fp1)c=fgetc(fp1);fputc(c,fp2);fclose(
15、fp1);fclose(fp2);return 0;打开多个文件if(fp1=fopen(f1.dat,r)=NULL)printf(File open error!n);exit(0);if(fp2=fopen(f2.dat,w)=NULL)printf(File open error!n);exit(0);C语言允许同时打开多个文件语言允许同时打开多个文件l 不同的文件对应不同的文件指针不同的文件对应不同的文件指针l 不允许同一个文件在关闭前再次打开不允许同一个文件在关闭前再次打开文件读写函数n 字符读写函数字符读写函数:fgetc/fputcn 字符串读写函数:字符串读写函数:fputs
16、/fgetsn 格式化读写函数:格式化读写函数:fscanf/fprintfn 二进制读写函数:二进制读写函数:fread/fwriten 其他相关函数:其他相关函数:l 检测文件结尾函数检测文件结尾函数feofl 检测文件读写出错函数检测文件读写出错函数ferrorl 清除末尾标志和出错标志函数清除末尾标志和出错标志函数clearerrl 文件定位的函数文件定位的函数fseek9.3.2 字符读写函数fgetc和fputcwhile(!feof(fp1)c=fgetc(fp1);fputc(c,fp2);n 函数函数fputc()l fputc(ch,fp);把一个字符把一个字符 ch 写到
17、写到 fp 所指示的磁盘文件上所指示的磁盘文件上l 返回值返回值n-1(EOF):写文件失败:写文件失败nch:写文件成功:写文件成功字符读写函数fgetc和fputcn 函数函数fgetc()ch=fgetc(fp);从从fp所指示的磁盘文件上读入一个字符到所指示的磁盘文件上读入一个字符到chl 区分键盘字符输入函数区分键盘字符输入函数getchar()从键盘输入从键盘输入10个字符,写到文件个字符,写到文件 f2.txt 中,再重中,再重新读出,并在屏幕上显示验证。新读出,并在屏幕上显示验证。键盘输入键盘输入 写入文件写入文件 f2.txt 读文件读文件 屏幕显示的屏幕显示的过程过程l 键
18、盘输入键盘输入 f2.txt时,文件按写方式打开。时,文件按写方式打开。l f2.txt 显示到屏幕时,文件按读方式打开。显示到屏幕时,文件按读方式打开。l 读和写是两种不同的操作,读和写是两种不同的操作,f2.txt 分别被打开和关闭两次。分别被打开和关闭两次。例9-4源程序int main(void)int i;char ch;FILE*fp;if(fp=fopen(f2.txt,w)=NULL)/*打开文件打开文件f2.txt */printf(File open error!n);exit(0);for(i=0;i 10;i+)/*写文件写文件10次次 */ch=getchar();f
19、putc(ch,fp);if(fclose(fp)/*关闭文件关闭文件 */printf(Can not close the file!n);exit(0);if(fp=fopen(f2.txt,r)=NULL)/*打开文件打开文件f2.txt */printf(File open error!n);exit(0);for(i=0;i 10;i+)/*读文件读文件10次次 */ch=fgetc(fp);putchar(ch);if(fclose(fp)/*再次关闭文件再次关闭文件 */printf(Can not close the file!n);exit(0);return 0;9.3.3
20、 字符串方式读写函数fgets和fputsn 函数函数fputs()fputs(s,fp);用来向指定的文本文件写入一个字符串用来向指定的文本文件写入一个字符串l s:要写入的字符串,结束符:要写入的字符串,结束符0不写入文不写入文件。件。l 函数返回值函数返回值n 执行成功,函数返回所写的最后一个字符执行成功,函数返回所写的最后一个字符n 否则,函数返回否则,函数返回EOF字符串方式读写函数fgets和fputsn 函数函数fgets()fgets(s,n,fp);从文本文件中读取字符串从文本文件中读取字符串l s:可以是字符数组名或字符指针;:可以是字符数组名或字符指针;n:指定读入的字符
21、:指定读入的字符个数;个数;fp:文件指针:文件指针l 函数被调用时,最多读取函数被调用时,最多读取n-1个字符,并将读入的字符串个字符,并将读入的字符串存入存入s所指向内存地址开始的所指向内存地址开始的n-1个连续的内存单元中。个连续的内存单元中。当函数读取的字符达到指定的个数,或接收到换行符,或接收到文当函数读取的字符达到指定的个数,或接收到换行符,或接收到文件结束标志件结束标志EOF时,将在读取的字符后面自动添加一个时,将在读取的字符后面自动添加一个0字字符;若有换行符,则将换行符保留(换行符在符;若有换行符,则将换行符保留(换行符在0字符之前);字符之前);若有若有EOF,则不保留,则
22、不保留l 函数返回值函数返回值n执行成功,返回读取的字符串;执行成功,返回读取的字符串;n如果失败,则返回空指针,这时,如果失败,则返回空指针,这时,s的内容不确定的内容不确定将字符串将字符串apple,grape,pear 写入到磁盘文件写入到磁盘文件f9-5.txt中,然后再中,然后再从该文件中读出,显示到屏幕。从该文件中读出,显示到屏幕。int main(void)FILE*fp;char a 80=apple,grape,pear,strout80=;int i;if(fp=fopen(f9-5.txt,w)=NULL)printf(File open error!n);exit(0)
23、;for(i=0;i 3;i+)fputs(ai,fp);fclose(fp);if(fp=fopen(f12-5.txt,r)=NULL)printf(File open error!n);exit(0);i=0;while(!feof(fp)if(fgets(strout,strlen(ai+)+1,fp)!=NULL)puts(strout);fclose(fp);return 0;例9-59.3.4 格式化文件读写fscanf和fprintfn fscanf(文件指针,格式字符串,输入表(文件指针,格式字符串,输入表);n fprintf(文件指针,格式字符串,输出表(文件指针,格式字
24、符串,输出表);指定格式的输入输出函数指定格式的输入输出函数FILE *fp;int n;float x;fp=fopen(a.txt,r);fscanf(fp,%d%f,&n,&x);表示从文件表示从文件a.txt分别读入整型数到变量分别读入整型数到变量n、浮点数到变量、浮点数到变量xfp=fopen(b.txt,w);fprintf(fp,%d%f,n,x);表示把变量表示把变量n和和x的数值写入文件的数值写入文件b.txt9.3.5 数据块读写fread()和fwrite()n fread(buffer,size,count,fp);从二进制文件中读入一个数据块到变量从二进制文件中读入一
25、个数据块到变量n fwrite(buffer,size,count,fp);向二进制文件中写入一个数据块向二进制文件中写入一个数据块l buffer:指针,表示存放数据的首地址;:指针,表示存放数据的首地址;l size:数据块的字节数:数据块的字节数l count:要读写的数据块块数:要读写的数据块块数l fp:文件指针:文件指针9.3.6 其他相关函数n 函数函数feoffeof(fp);判断判断fp指针是否已经到文件末尾,指针是否已经到文件末尾,函数返回值函数返回值n 1:到文件结束位置:到文件结束位置n 0:文件未结束:文件未结束其他相关函数n 函数函数rewind()rewind(F
26、ILE*fp);定位文件指针,使文件指针指向读写文件的首地址,定位文件指针,使文件指针指向读写文件的首地址,即打开文件时文件指针所指向的位置。即打开文件时文件指针所指向的位置。其他相关函数n 函数函数fseek()fseek(fp,offset,from);用来控制指针移动用来控制指针移动l offset:移动偏移量,:移动偏移量,long型型l from:起始位置,文件首部、当前位置和文件尾部分别对:起始位置,文件首部、当前位置和文件尾部分别对应应0,1,2,或常量,或常量SEEK_SET、SEEK_CUR、SEEK_END。例如:例如:fseek(fp,20L,0):将文件位置指针移动到离
27、文件首:将文件位置指针移动到离文件首20字节处字节处fseek(fp,-20L,SEEK_END):将文件位置指针移动到离文件尾:将文件位置指针移动到离文件尾部前部前20字节处字节处其他相关函数n 函数函数ftell()ftell(文件指针文件指针);获取当前文件指针的位置,即相对于文件开头的位获取当前文件指针的位置,即相对于文件开头的位移量(字节数)移量(字节数)l 函数出错时,返回函数出错时,返回-1L9.3.6 其他相关函数n 5ferror函数:函数用来检查文件在用函数:函数用来检查文件在用各种输入输出函数进行读写是否出错,若各种输入输出函数进行读写是否出错,若返回值为返回值为0,表示
28、未出错,否则表示有错,表示未出错,否则表示有错 调用形式为:调用形式为:l 文件指针必须是已经定义过的文件指针必须是已经定义过的其他相关函数n 函数函数clearerr()clearerr(文件指针文件指针);用来清除出错标志和文件结束标志,使它们为用来清除出错标志和文件结束标志,使它们为09.4 文件综合应用:个人小金库的管理n9.4.1顺序文件和随机文件顺序文件和随机文件 按照按照C程序对文件访问的特点来分,文件可分为顺序访问文件程序对文件访问的特点来分,文件可分为顺序访问文件和随机访问文件,简称为顺序文件和随机文件。前面介绍的所有例和随机访问文件,简称为顺序文件和随机文件。前面介绍的所有
29、例子都进行的是顺序访问,通过使用子都进行的是顺序访问,通过使用fprintf或或fputs函数创建的数据函数创建的数据记录长度并不是完全一致的,这种记录长度不确定的文件访问称为记录长度并不是完全一致的,这种记录长度不确定的文件访问称为顺序访问。而随机访问文件要求文件中单个记录的长度固定,可直顺序访问。而随机访问文件要求文件中单个记录的长度固定,可直接访问,这样速度快,并且无需通过其他记录查找特定记录。因此接访问,这样速度快,并且无需通过其他记录查找特定记录。因此随机文件适合银行系统、航空售票系统、销售点系统和其他需要快随机文件适合银行系统、航空售票系统、销售点系统和其他需要快速访问特定数据的事
30、务处理系统。速访问特定数据的事务处理系统。9.4.2 个人小金库的管理n 要求要求l 小金库的信息统一放在随机文件中小金库的信息统一放在随机文件中,该随机文该随机文件包括的数据项有记录件包括的数据项有记录ID、发生日期、发生、发生日期、发生事件、发生金额(正的表示收入,负表示支出)事件、发生金额(正的表示收入,负表示支出)和余额。每记录一次收支,文件要增加一条记和余额。每记录一次收支,文件要增加一条记录,并计算一次余额。录,并计算一次余额。l 程序可以创建该文件并添加新收入或支出信息,程序可以创建该文件并添加新收入或支出信息,可进行查询得知小金库的收支流水帐即收入、可进行查询得知小金库的收支流
31、水帐即收入、支出及余额信息。支出及余额信息。cashbox.txt文件的部分内容LogID CreateDateNoteChargeBalance12006-06-01 alimony500.00500.0022006-06-08 shopping-300.00200.0032006-06-15 shopping-60.00140.0042006-06-20 workingpay 200.00340.0052006-08-01 scholarship 1000.001340.00本章小结p 文件的概念,文件的存储;文件的概念,文件的存储;p 文件的打开与关闭;文件的打开与关闭;p 文件读写;文件读写;p 应用实例。应用实例。