1、 第12章 文件程序设计技术基础-C语言本章重点内容(1)文本文件和二进制文件(2)文件的打开与关闭(3)文件的顺序读写与随机读写2022-8-82程序设计技术基础-C语言12.1 文件的基本概念 12.1.1 文件概述 所谓“文件”一般是指存储在外部介质上的一组数据的有序集合。C语言将文件看作是字符(字节)序列,即一个一个字符(字节)的数据顺序组成。2022-8-83程序设计技术基础-C语言12.1 文件的基本概念 12.1.2 文件的分类 1.从用户的角度看,文件可分为普通文件和设备文件。2.按文件存储数据的内容来分,文件可分为程序文件和数据文件。3按文件中数据的存储方式来分,文件可分为文
2、本文件(也称ASCII文件)和二进制文件。2022-8-84程序设计技术基础-C语言12.1 文件的基本概念 12.1.3 缓冲文件系统 缓冲文件系统,又称为标准文件系统。当使用标准I/O函数(包含在头文件stdio.h中)时,系统会自动在内存为程序中每一个正在使用的文件开辟一个“缓冲区”,作为程序与数据文件之间数据交换的中间媒介。2022-8-85程序设计技术基础-C语言12.2 文件的操作流程 对于缓冲文件系统,用户程序使用一个文件的操作流程通常为4个步骤:定义文件类型指针、打开文件、读写操作、关闭文件。2022-8-86程序设计技术基础-C语言12.3 文件的打开与关闭 12.3.1 文
3、件的打开 打开文件通过系统提供的fopen函数实现。其函数调用的形式为:文件指针名=fopen(文件名,使用文件方式);2022-8-87程序设计技术基础-C语言12.3.1 文件的打开 说明:1.“文件指针名”:文件指针名必须是被说明为FILE 类型的指针变量。fopen函数在执行时返回一个FILE类型的指针,通常赋给一个文件指针变量。例如:FILE*fp;fp=fopen(file a,r);2022-8-88程序设计技术基础-C语言12.3.1 文件的打开 说明:2.“文件名”:是被打开文件的文件名,可以包含路径和文件名两部分。例如:FILE*fp;fp=(d:abc.txt,r);其意
4、义是打开D盘根目录下的abc.txt文件。2022-8-89程序设计技术基础-C语言12.3.1 文件的打开 说明:3.“使用文件方式”:表示文件的打开方式,指文件的类型和操作要求。使用文件方式的取值共有12种,表12-1给出了其每种取值及含义。2022-8-810程序设计技术基础-C语言12.3.1 文件的打开 2022-8-811“使使用文件方用文件方式式”的取的取值值含义含义R以只读方式,打开一个文本文件。只允许读取,不允许写入。该文件必须存在,文件不存在时,返回错误标识。W 以只写方式,创建并打开一个文本文件。只允许写入,不允许读取。文件不存在时,建立新文件。文件存在时,原文件被覆盖。
5、A以追加方式打开一个文本文件。只允许写入。文件存在时,打开文件,只能从文件尾向文件追加数据,文件原先的内容会被保留。文件不存在时,建立新文件。r+以读写方式打开一个文本文件。允许读取和写入。该文件必须存在,文件不存在时,返回错误标识。w+以读写方式建立一个新的文本文件。允许读取和写入。文件存在时,打开文件,原文件内容清空。文件不存在时,建立新文件。a+以追加方式打开可读写的文本文件。允许读取和写入。如果文件不存在,建立新文件。如果文件存在,可从文件中读取或往文件中写入数据,写入的数据会被加到文件尾后,文件原先的内容会被保留。rb以只读方式打开一个二进制文件。只允许读取,不允许写入。该文件必须存
6、在,文件不存在时,返回错误标识。wb以只写方式打开一个二进制文件。只允许写入。文件存在时,打开文件,原文件内容清空。文件不存在时,建立新文件。ab以追加方式打开一个二进制文件。文件存在时,打开文件,从文件尾向文件追加数据。文件不存在时,建立新文件。rb+以读写方式打开一个二进制文件。允许读取和写入。该文件必须存在。如果文件不存在时,返回错误标识。wb+以读写方式建立一个新的二进制文件。允许读和写文件存在时,打开文件,原文件内容清空。文件不存在时,建立新文件。ab+以读写方式打开一个二进制文件。文件存在时,打开文件,可从文件读取或往文件中写入数据。文件不存在时,建立新文件。程序设计技术基础-C语
7、言12.3.1 文件的打开 说明:“使用文件方式“的取值由r、w、a、t、b、+六个字符拼成,各字符的含义如下。r(read):读取数据w(write):写入数据a(append):追加数据t(text):文本文件,可省略不写b(banary):二进制文件+:可读取和写入 2022-8-812程序设计技术基础-C语言12.3.2 文件的关闭C语言中,关闭文件通过系统提供的fclose函数实现。函数调用的形式为:fclose(文件指针);关闭文件就是使原来指向该文件的文件指针与文件脱离,以便再使用该文件指针时,不会对该文件进行读写操作,除非再次打开该文件。fclose函数的返回值有两种:0和非零
8、值。正常完成关闭文件操作时,fclose函数返回值为0。如返回非零值则表示文件关闭失败。例如:fclose(fp);前面把打开文件时函数返回的指针赋给了fp,现在把fp指向的文件关闭,此后fp不再指向该文件。2022-8-813程序设计技术基础-C语言12.4 文件的顺序读写 文件打开之后,就可以对它进行读写操作了。文件的顺序读写是指文件被打开之后,读写数据的顺序和数据在文件中的物理顺序是一致的,即读写文件只能从头开始,每读写一次后,文件读写位置标记会自动指向下一个位置。在C语言中,常见的文件的读写方式包括:按字符读写文件、按字符串读写文件、按格式读写文件和按数据块读写文件。这几种读写操作都是
9、通过函数调用来实现的,使用这些函数都要求包含头文件stdio.h。2022-8-814程序设计技术基础-C语言12.4 文件的顺序读写 12.4.1 按字符读写文件按字符读写文件是以字符(字节)为单位对文件进行读写操作。每次可从文件读出一个字符或向文件写入一个字符。C语言提供了按字符方式读写文件的函数:写字符函数fputc和读字符函数fgetc。1写字符函数:fputc函数函数调用的形式为:fputc(字符量,文件指针);功能:把一个字符写入文件指针所指的文件中。例如:fputc(w,fp);其意义是把字符“w”写入fp所指向的文件中。2022-8-815程序设计技术基础-C语言12.4 文件
10、的顺序读写 12.4.1 按字符读写文件1写字符函数:fputc函数说明:(1)参数“字符量”是要输出的字符,它可以是一个字符常量,也可以是一个字符变量。(2)被写入的文件可以用写、读写,追加方式打开,用写或读写方式打开一个已存在的文件时将清除原有的文件内容,从文件首开始写入字符。如需保留原有文件内容,希望写入的字符以文件末尾开始存放,必须以追加方式打开文件。被写入的文件若不存在,则创建该文件。(3)每写入一个字符,文件读写位置标记向后移动一个字节。(4)文件读写位置标记与文件指针的区别:在文件内部有一个文件读写位置标记,用来指向文件的当前读写字节。在文件打开时,该标记总是指向文件的第一个字节
11、,完成一次读或写后,该位置标记将向后移动一个字节。需要注意文件指针和文件读写位置标记不是同一个指针。文件指针是指向整个文件的,必须在程序中定义说明。文件读写位置标记用以指向文件内部的当前读写位置,每读写一次,该标记均向后移动,它是由系统自动设置的,不需在程序中定义说明。(5)fputc函数有一个返回值,如果写入成功则返回写入的字符,否则返回一个EOF。可用此来判断写入是否成功。EOF是在stdio.h库函数文件中定义的符号常量,值为-1。EOF也是文件的结束标志。2022-8-816程序设计技术基础-C语言12.4 文件的顺序读写 2读字符函数:fgetc函数 函数调用的形式为:字符变量=fg
12、etc(文件指针);功能:从文件指针所指向的文件中读一个字符。例如:ch=fgetc(fp);其含义是从打开的文件fp中读取一个字符并送入ch中。说明:(1)在fgetc函数调用中,读取的文件必须是以读或读写方式打开的。(2)读取字符的结果也可以不向字符变量赋值。例如:fgetc(fp);但是读出的字符不能保存。【例12-1】从键盘输入1串字符,写到磁盘文件student.txt中,以回车作为该行结束;再把该文件内容读出并显示在屏幕上。2022-8-817程序设计技术基础-C语言12.4 文件的顺序读写【例12-1】从键盘输入1串字符,写到磁盘文件student.txt中,以回车作为该行结束;
13、再把该文件内容读出并显示在屏幕上。2022-8-818#include#includeintmain()FILE*fp;charch;if(fp=fopen(student.txt,w)=NULL)printf(Fileopenerror!n);exit(0);ch=getchar();while(ch!=n)fputc(ch,fp);ch=getchar();fclose(fp);if(fp=fopen(student.txt,r)=NULL)printf(Fileopenerror!n);exit(0);ch=fgetc(fp);while(ch!=EOF)putchar(ch);ch=f
14、getc(fp);fclose(fp);return0;/*定义文件指针定义文件指针*/*打开文件打开文件student.txt*/*从键盘输入一个字符从键盘输入一个字符*/*循环写文件循环写文件*/*把字符写入文件把字符写入文件*/*关闭文件关闭文件*/*再次打开文件再次打开文件student.txt*/*从文件中读出一个字符从文件中读出一个字符*/*把字符显示在屏幕上把字符显示在屏幕上*/*关闭文件关闭文件*/程序设计技术基础-C语言12.4 文件的顺序读写 12.4.2 按字符串读写文件将字符串写入文件中可使用函数fputs,从文件中读取字符串可使用函数fgets。1.写字符串函数:fp
15、uts函数函数调用的形式为:fputs(字符串,文件指针);功能:将字符串写入文件指针所指的文件中。例如:fputs(abcd,fp);其意义是把字符串“abcd”写入fp所指的文件之中。说明:(1)fputs函数带有返回值:若写入成功返回正整数,否则返回-1(EOF)。(2)字符串结束符不被写入文件。为了读取数据方便,设法使字符串分开,常常用fputs(n,fp)语句在每个字符串后面加一个换行符n一起存入文件中。2022-8-819程序设计技术基础-C语言12.4 文件的顺序读写 12.4.2 按字符串读写文件1.写字符串函数:fputs函数【例12-2】用写字符串函数将表12-2中3名学生
16、的数据,由键盘输入并存储到磁盘文件studenttxt中。2022-8-820表表12-2学生学生信息信息学学号号姓 名成 绩20170901Zhangping25320170902Limaochang26820170903Wangwenhua245程序设计技术基础-C语言程序代码如下:#include#include#define N 3int main()int i;char string80;FILE*fp;if(fp=fopen(student.txt,w)=NULL)puts(n cant open file student.txt!n);exit(0);for(i=0;i N;i+
17、)printf(please input the student%dn,i+1);printf(number:);gets(string);fputs(string,fp);fputs(n,fp);printf(name:);gets(string);fputs(string,fp);fputs(n,fp);printf(score:);gets(string);fputs(string,fp);fputs(n,fp);fclose(fp);return 0;2022-8-821程序设计技术基础-C语言12.4 文件的顺序读写 12.4.2 按字符串读写文件2读字符串函数:fgets函数 函数
18、调用的形式为:fgets(字符数组,n,文件指针);功能:从文件指针所指的文件中读取一个字符串到字符数组中。例如:fgets(str,n,fp);其含义是从fp所指的文件中读出n-1个字符送入字符数组str中。说明:(1)该函数从文件指针所指的文件中,读取的字符串不超过 n-1个字符。当读满n-1个字符前,若遇到换行符或文件结束符(EOF),函数停止读操作,并在字符串的最后一个字符后加上一个串结束符0。需要注意的是,如果遇到换行符,fgets函数将换行符也作为字符串的一部分读取。(2)fgets函数的返回值是字符数组的首地址。若读取失败时,返回空指针NULL。2022-8-822程序设计技术基
19、础-C语言【例12-3】从student.txt文件中读取一个含10个字符的字符串。程序代码如下:#include#includeintmain()FILE*fp;charstr11;if(fp=fopen(student.txt,r)=NULL)p r i n t f(n C a n n o t o p e n f i l e s t r i k e a n y k e y e x i t!);exit(0);gets(str,11,fp);printf(n%sn,str);fclose(fp);return0;/*定义文件指针定义文件指针*/*打开文件打开文件student.txt*/*从
20、文件中读入一个字符串从文件中读入一个字符串*/*关闭文件关闭文件*/2022-8-823程序设计技术基础-C语言12.4 文件的顺序读写 12.4.3 按数据块读写文件fgets函数有局限性,每次最多只能从文件中读取一行内容,因为 fgets 遇到换行符就会结束读取操作。如果希望一次读写多行内容,C语言还提供了用于整块数据的读写函数fread和fwrite,即按数据块读写文件。这两个函数多用于读写二进制文件。1写数据块函数:fwrite函数其函数调用的形式为:fwrite(ptr,size,count,fp);功能:将ptr所指向的内存区域中的数据块写入fp所指向的文件中。说明:(1)ptr是
21、一个指针,即内存地址,是待输出数据块的起始地址;size是无符号整数,表示每个数据块的字节数;count是无符号整数,表示要读写的数据块块数;fp表示文件指针。(2)每次写入文件的数据块共有count项,每项长度为size个字节,因此每次写入数据的字节总数为 count*size。2022-8-824程序设计技术基础-C语言【例12-4】把表12-2中的N个学生信息以二进制文件形式存储在文件studentbin中。程序代码如下:#include#defineN3typedefstructstudentcharno15;charname15;intscore;STUDENT;intmain()F
22、ILE*fp;STUDENTstu;inti;fp=fopen(student.bin,wb);/*按二进制方式打开文按二进制方式打开文件件*/for(i=0;iN;i+)printf(inputtheno,name,scoren);scanf(%s%s%d,&stu.no,&stu.name,&stu.score);fwrite(&stu,sizeof(stu),1,fp);/*将学生信息写入文件将学生信息写入文件*/fclose(fp);return0;2022-8-825程序设计技术基础-C语言12.4 文件的顺序读写 12.4.3 按数据块读写文件2读数据块函数:fread函数其函数调
23、用的形式为:fread(ptr,size,count,fp);功能:从文件指针fp所指的文件中读取数据块并存储到ptr指向的内存中。说明:参数ptr是一个指针,即内存地址,是将要存放读入数据的变量地址或数组的起始地址。例如:fread(fs,4,6,fp);其含义是从fp所指的文件中,每次读4个字节(一个实数)送入实数组fs中,连续读6次,即读6个实数到fs中。2022-8-826程序设计技术基础-C语言【例12-5】从键盘输入一个数组,将数组写入文件,再读取出来。程序代码如下:#include#include#include#defineN5intmain()FILE*fp;intaN,bN
24、;/*从键盘输入的数据放入从键盘输入的数据放入a,从文件读取的数据放入,从文件读取的数据放入b*/inti,size=sizeof(int);if(fp=fopen(D:file1.txt,rb+)=NULL)printf(Cannotopenfile,pressanykeytoexit!n);getch();exit(1);for(i=0;iN;i+)scanf(%d,&ai);/*从键盘输入数据从键盘输入数据并保存到数组并保存到数组a*/fwrite(a,size,N,fp);/*将数组将数组a的内容写入到文件的内容写入到文件*/rewind(fp);/*将文件中的位置指针重新定位到文件开
25、头将文件中的位置指针重新定位到文件开头*/fread(b,size,N,fp);/*从文件读取内容并保存到数组从文件读取内容并保存到数组b*/for(i=0;iN;i+)/*在屏幕上显示数组在屏幕上显示数组b的内容的内容*/printf(%d,bi);printf(n);fclose(fp);return0;2022-8-827程序设计技术基础-C语言12.4 文件的顺序读写 12.4.4 按格式读写文件C语言允许按指定格式读写文件。fscanf函数用于按指定格式从文件读数据;fprintf 函数用于按指定格式向文件写数据。fscanf函数和 fprintf函数与前面使用的 scanf函数和
26、printf 函数功能相似,都是格式化读写函数,但两者的不同在于 fscanf函数 和 fprintf函数 的读写对象不是键盘和显示器,而是磁盘文件。1.格式化写函数:fprintf函数其函数调用的形式为:fprintf(文件指针,格式字符串,输出表列);功能:将指定变量的值按照指定格式写入文件指针指向的文件。2022-8-828程序设计技术基础-C语言【例12-6】将从键盘输入的5行字符数据存入file1.txt文件中。程序代码如下:#includevoidmain()charc520;inti;FILE*fp;for(i=0;i5;i+)gets(ci);fp=fopen(file1.tx
27、t,w);for(i=0;i5;i+)fprintf(fp,%sn,ci);fclose(fp);2022-8-829程序设计技术基础-C语言12.4 文件的顺序读写 12.4.4 按格式读写文件2.格式化读函数:fscanf函数其函数调用的形式为:fscanf(文件指针,格式字符串,输入表列);功能:从文件指针指向的文件中,按照说明的格式向指定变量提供数据。例如:fprintf(fp,%d%c,j,ch);说明:fscanf函数中的参数格式字符串、输入表列的含义与scanf函数的参数是相同的;fscanf函数与scanf函数在用法上基本相同,区别在于scanf函数是从控制台读入数据,而fsc
28、anf函数是从文件中读入数据。用函数fscanf和 fprintf进行文件的格式化读写,读写方便,易于理解。比如用函数fprintf和fscanf读写配置文件、日志文件会非常方便,不但程序能够识别,用户也可以看懂,可以手动修改。2022-8-830程序设计技术基础-C语言【例12-7】从键盘输入5个实数,存入文件file2.dat中,每个实数用逗号分隔,并将这5 个数据输出到屏幕上。程序代码如下:#include#includeintmain()floatf;inti;FILE*fp;fp=fopen(file2.dat,w);for(i=0;i5;i+)scanf(%f,&f);fprint
29、f(fp,%f,f);fclose(fp);fp=fopen(file2.dat,r);for(i=0;i5;i+)fscanf(fp,%f,&f);printf(%fn,f);fclose(fp);return0;2022-8-831程序设计技术基础-C语言12.5 文件的随机读写 文件的随机读写,是指在对文件进行读写操作时,可以直接将读写位置标记(位置指针)定位到需要读写的位置,进行读写操作。前面介绍的文件顺序读写,只能从头开始,顺序读写各个数据。在实际问题中常要求只读写文件中某一指定的部分,解决这个问题可采用随机读写方式,以提高读写文件效率。实现随机读写的关键是如何按要求移动文件的读写位
30、置标记,这称为文件的定位。C语言提供了一组用于文件随机读写的函数,其中移动文件读写位置标记的函数主要有两个:rewind函数和fseek函数。2022-8-832程序设计技术基础-C语言12.5 文件的随机读写 1.重定位函数:rewind函数其函数调用的形式为:rewind(文件指针);功能:把文件内部的读写位置标记重新指向文件首。例如:rewind(fp1);说明:在实际应用中,如果对某一个文件进行多次读写操作后,需要重新读写该文件,可以采用关闭该文件再打开该文件的方法,使读写位置标记指向文件首,也可以使用rewind函数在不关闭文件的情况下将读写位置标记返回文件首。2022-8-833程
31、序设计技术基础-C语言12.5 文件的随机读写 2.随机定位函数:fseek函数其函数调用的形式为:fseek(文件指针,位移量,起始点)功能:将文件指针所指文件的读写位置标记移动到指定的位置,指示下一个要读写的数据位置。说明:(1)“文件指针”指向被定位的文件;“位移量”表示以“起始点”为基点移动的字节数,一般要求“位移量“为long型,以便移动的范围更大,能处理的文件更大。当用常量表示位移量时,要求加后缀“L”;“起始点”表示从何处开始计算位移量,C语言规定的起始点有三种,分别为文件首、当前位置和文件末尾,每个位置都用对应的常量来表示。其表示方法如表12-3所示。2022-8-834程序设
32、计技术基础-C语言12.5 文件的随机读写 表表12-3起始点的表示方法起始点的表示方法起始点起始点表示符号数字表示文件首文件首SEEK_SET0当前位置当前位置SEEK_CUR1文件末尾文件末尾SEEK_END22022-8-835程序设计技术基础-C语言12.5 文件的随机读写 2022-8-836说明(2)fseek函数一般用于二进制文件。通过fseek函数可以对文件进行随机定位,也就是说可以将文件的读写位置标记移到文件中任意指定的位置,文件的随机读写在移动读写位置标记之后,即可用前面介绍的任意一种读写函数进行读写。例如,要读入文件中倒数第2个字节的字符,则可将文件的读写位置标记移到距文
33、件末尾2个字节的位置,然后读取该位置的字符,假设文件指针为fp,则相应的语句为:fseek(fp,-2L,2);fgetc(fp);或fseek(fp,-2L,SEEK_END);fgetc(fp);程序设计技术基础-C语言12.5 文件的随机读写 2022-8-8373.位置函数:ftell函数其函数调用的形式为:ftell(文件指针);功能:获得文件读写位置标记的当前位置,给出当前读写位置标记相对于文件首的字节偏移量,返回当前位置,如果出错则返回-1L。例如:i=ftell(fp);if(i=-1L)printf(“errorn”);变量i存放文件读写位置标记的当前位置,如果调用函数出错则
34、输出“error”。【例12-8】从键盘输入表12-1中的 N个学生信息,存储在文件studentbin中,并读取第二个学生信息。程序设计技术基础-C语言#include#include#include#defineN3structstuintnum;/*学号学号*/charname15;/*姓名姓名*/intscore;/*成绩成绩*/stussN,stus,*pstus;intmain()FILE*fp;inti;pstus=stuss;if(fp=fopen(e:studentbin,wb+)=NULL)printf(Cannotopenfile,pressanykeytoexit!n)
35、;getch();exit(1);printf(Inputdata:n);for(i=1;inum,&pstus-name,&pstus-score);fwrite(stuss,sizeof(structstu),N,fp);/*写入三条学生信息写入三条学生信息*/fseek(fp,sizeof(structstu),SEEK_SET);/*移动位置指针移动位置指针*/fread(&stus,sizeof(structstu),1,fp);/*读取一条学生信息读取一条学生信息*/printf(%d%s%dn,stus.num,stus.name,stus.score);fclose(fp);r
36、eturn0;2022-8-838【例12-8】从键盘输入表12-1中的 N个学生信息,存储在文件studentbin中,并读取第二个学生信息。程序代码如下:程序设计技术基础-C语言 12.6 文件操作的错误检测2022-8-8391.文件结束检测函数:feof 函数其函数的调用形式为:feof(文件指针);功能:判断文件是否处于文件结束位置,如文件结束,则返回值为1,否则返回值为0。2.读写文件出错检测函数:ferror函数其函数的调用形式为:ferror(文件指针);功能:检查文件在用各种输入输出函数进行读写时是否出错。如ferror返回值为0,表示未出错,否则表示有错。通常,在调用一个输
37、入输出函数后立即检查ferror函数的值,否则信息会丢失。在执行fopen函数时,ferror函数的初始值自动置为。3.文件出错标志和文件结束标志置函数:clearerr函数其函数的调用形式为:clearerr(文件指针);功能:本函数用于清除出错标志和文件结束标志,使它们为0值。程序设计技术基础-C语言2022-8-840 本章主要介绍了文件的相关概念及用户程序使用文件的操作方法。文件是指存储在外部介质上的数据集合。按文件中数据的存储方式来分,文件分为文本文件和二进制文件。ANSI C标准采用“缓冲文件系统”处理数据文件,缓冲文件系统定义了文件操作的相关函数。文件的操作顺序是“打开文件”、“读写文件”及“关闭文件”。本章小结注意本章节知识点!