第九章文件★内容提要:文本文件与二进制文件缓冲文件系统概念文件的指针文件的打开与关闭文件应用文件分类缓冲文件系统文件的指针文件打开与关闭文件应用第九章文件文件是指存储在外部介质上,且按文件名访问的一组信息序列。一、文件分类文本文件(字符代码文件或ASCII代码文件)由一个一个字符组成,每一个字符用一个ASCII代码表示,如123.45以ASCII代码形式存储到磁盘需要6个字节。特点:可通过显示器或打印机显示,即可读,比较直观。一、文件分类非文本文件(二进制文件):是指以数据在内存中的存储形式原样输出存储到磁盘上的文件。如123.45在内存中以浮点数形式存储占4个字节,不管一个实数多大都占4字节。特点:节省存储空间,输入输出无需转换速度快,不便阅读。说明:一个C文件是一个字节流或二进制流,它把数据看作是一连串的字符序列(字节),而不考虑记录的界限,即C文件并不是由记录组成的。由于对文件的操作要与各种外部设备发生联系,因此对文件的输入输出(读写)过程是通过操作系统来实现的。对文件的读写都是通过标准的I/O函数进行的。二、缓冲文件系统(标准I/O)和非缓冲文件系统缓冲文件系统(又称标准或高层文件系统)特点:对程序中的每一个文件都在内存中开辟一个“缓冲区”。作用:从磁盘文件读入的数据先送到“输入缓冲区”中,然后再从缓冲区依次将数据送给接收变量。在向磁盘文件输出数据时,先将程序数据区中变量或表达式的值送到“输出文件缓冲区”中,待装满后才一起输出给磁盘文件。目的减少对磁盘的读写次数,即一次可以读入一批数据或输出一批数据。输入文件缓冲区(512KB)输出文件缓冲区(512KB)变量a程序数据区磁盘文件读写内存二、缓冲文件系统(标准I/O)和非缓冲文件系统非缓冲文件系统:不由系统自动设置所需缓冲区,而由用户自己根据需要设置。新的ANSI标准只建议使用缓冲系统,并对缓冲文件系统的功能进行了扩充,使既能用于处理字符代码文件,也能处理二进制文件。三、文件型指针类型对文件的操作是通过文件指针实现的。关键的概念是“文件指针”。调用一个文件需要的信息:文件当前读写的位置;与该文件对应的内存缓冲区的地址;缓冲区未被处理的字符数(字符指针);文件的操作方式等三、文件型指针类型系统内部定义了一个称FILE的结构型类型。typedefstruct{int_fd;//文件号int_cleft;//缓冲区中剩余的字符int_mode;//文件操作模式char*_nextc;//下一个字符位置char*_buff;//文件缓冲区位置}FILE;四、文件的打开和关闭文件必须先打开后,并及时关闭。1.打开文件:是在用户程序和操作系统之间建立起联系,程序要把操作的文件的一些信息通知操作系统,如文件名、文件操作方式(读/写):读文件:需要先确认此文件是否已存在,并将读当前位置设定为文件的开头。写文件:需要检查原来是否有同名文件,如有则将该文件原有内容删除,如无同名文件就建立一个新文件,然后将写当前位置设定于文件的开头,以便从文件开头写入数据。1.文件的打开方式:FILE*fp;if((fp=fopen(文件名,使用文件方式))==NULL){printf(cannotopenthisfile.\n);exit(0);}说明:文件名可以是字符串常量、数组名或字符指针。使用文件方式参见附表。FILE*fp;if((fp=fopen(文件名,使用文件方式))==NULL){printf(cannotopenthisfile.\n);exit(0);}文件输入/输出缓冲区…………………………用户程序与数据区磁盘文件读/写内存fp_fd文件号_cleft缓冲区中剩余的字符_mode文件操作方式*_nextc下一个字符位置(指针)*_buff文件缓冲区位置(指针)FILE相应的结构变量程序与外部文件的联接示意图,具体操作由文件管理系统负责文件输入/输出缓冲区…………………………用户程序与数据区磁盘文件读/写内存fp_fd文件号_cleft缓冲区中剩余的字符_mode文件操作方式*_nextc下一个字符位置(指针)*_buff文件缓冲区位置(指针)FILE相应的结构变量程序与外部文件的联接示意图,具体操作由文件管理系统负责文件使用方式文件使用方式含义r(只读)w(只写)a(追加)rb(只读)wb(只写)ab(追加)r+(读写)w+(读写)a+(读写)rb+(读写)wb+(读写)ab+(读写)为输入打开一个字符文件为输出打开一个字符文件向字符文件尾部增补数据为输入打开一个二进制文件为输出打开一个二进制文件向二进制文件尾部增补数为读/写打开一个字符文件为读/写建立一个新的字符文件为读/写打开一个字符文件为读/写打开一个二进制文件为读/写建立一个新的二进制文件为读/写打开一个二进制文件为输入打开一个字符文件为输出打开一个字符文件向字符文件尾部增补数据为输入打开一个二进制文件为输出打开一个二进制文件向二进制文件尾部增补数为读/写打开一个字符文件为读/写建立一个新的字符文件为读/写打开一个字符文件为读/写打开一个二进制文件为读/写建立一个新的二进制文件为读/写打开一个二进制文件2.文件的关闭文件的关闭形式:fclose(fp);功能:将fp所指文件关闭。释放文件有关信息区;将输出文件缓冲区的内容(无论缓冲区是否为满)都输出写入文件,然后关闭文件,这样可防止丢失本来应写入文件的数据。五、文件应用示例[例1]:格式化的输入输出。fprintf(fp,格式字符串,输出项表列)功能:将输出按格式串规定输出到fp所指文件。fscanf(fp,格式字符串,输入项表列)功能:从fp所指文件按格式串读入数据。函数执行成功返回读得的数据项个数;若在读第一项前已到达文件结束处,则返回EOF。#includestdio.h#includeprocess.h#includestring.hvoidmain(){FILE*fp;charname[10];intnum;floatscore;if((fp=fopen(file3.txt,w+))==NULL){printf(cannotopenthisfile.\n);exit(0);}printf(entername,num,score:);scanf(%s%d%f,name,&num,&score);while(strlen(name)1){fprintf(fp,%s%d%f\n,name,num,score);printf(entername,num,score:);scanf(%s%d%f,name,&num,&score);}rewind(fp);while(fscanf(fp,%s%d%f,name,&num,&score)!=EOF)printf(%-10s%6d%6.2f\n,name,num,score);fclose(fp);}输入:entername,num,score:zhangsan050190↙entername,num,score:liming050285↙entername,num,score:gaofei050395↙entername,num,score:000↙输出:zhangsan050190.00liming050285.00gaofei050395.00[例2]:数据块(二进制形式)的读写。fread(buffer,size,count,fp)功能:从指定文件读入count个大小为size的字节数据块,存入buffer所指存储单元。返回所读的数据项个数,如遇文件结束或出错返回0。fwrite(buffer,size,count,fp)功能:buffer所指存储单元的数据取size*count个字节送fp所指文件。返回写到fp所指文件中的数据项个数。[例2]:数据块(二进制形式)的读写。fread(buffer,size,count,fp)fwrite(buffer,size,count,fp)说明:buffer为输入输出在内存中存放的首地址。size为读、写的字节数,即数据块的大小。count为输入输出的数据项个数。fread()和fwrite()用于二进制文件的输入输出#includestdio.h#includeprocess.h#defineSIZE4structstudent{charname[10];intnum,age;charaddr[15];}stud[SIZE];voidsave_load(){FILE*fp;inti;if((fp=fopen(stu_list,wb+))==NULL){printf(cannotopenfile.\n);exit(0);}for(i=0;iSIZE;i++)if(fwrite(&stud[i],sizeof(structstudent),1,fp)!=1){printf(filewriteerror!\n);exit(0);}rewind(fp);for(i=0;iSIZE;i++)if(fread(&stud[i],sizeof(structstudent),1,fp)!=0)printf(%-10s%4d%4d%-15s\n,stud[i].name,stud[i].num,stud[i].age,stud[i].addr);}voidmain(){inti;for(i=0;iSIZE;i++)scanf(%s%d%d%s,stud[i].name,&stud[i].num,&stud[i].age,stud[i].addr);save_load();}输入:zhang100119room_101↙li100220room_102↙wang100321room_103↙zhao100421room_104↙输出:zhang100119room_101li100220room_102wang100321room_103zhao100421room_104[例3]:具有文件拷贝功能的程序filecopy.c说明两个问题:命令行参数的应用和文件的字符输入与输出应用。fgetc(fp)功能:从指定文件读入一个字符。fputc(ch,fp)功能:把一个字符写到指定文件中去。#includestdio.h#includeprocess.h#includestring.hfilecopy(FILE*fp1,FILE*fp2){charc;while((c=fgetc(fp1))!=EOF)fputc(c,fp2);}[例3]:具有文件拷贝功能的程序filecopy.cvoidmain(intargc,char*argv[]){filecopy(FILE*fp1,FILE*fp2);FILE*fp1,*fp2;if(argc1){if((fp1=fopen(*++argv,r))==NULL){printf(can\'tfopen%s\n,*argv);exit(0);}if((fp2=fopen(*++argv,w))==NULL){printf(can\'tfopen%s\n,*argv);exit(0);}filecopy(fp1,fp2);}}运行时情况:$vifilecopy.c↙$ccfile.c–ofilecopy↙$filecopyt.ct1.c↙fiecopy\0t.c\0t1.c\0argv[0]argv[1]argv[2]argv[]3argc运行时数据状态:fiecopy\0t.c\0t1.c\0argv[0]argv[1]argv[2]argv[]fiecopy\0t.c\0t1.c\0argv[0]argv[1]argv[2]argv[]3argc3argc运行时数据状态:fgets(str,n,fp)字符串输入函数。其功能是从fp指定的文件中读取一个串,若满足以下条件读取结束:①已读取n-1个字符、②当前读取到的字符是回车符、③已读取到文件尾。读取的字符