1、第十章第十章 文件文件 本章目录本章目录10.1文件概述文件概述10.2文件的打开与关闭文件的打开与关闭10.3文件的读写文件的读写10.4文件的定位文件的定位10.5 错误处理错误处理10.1文件概述文件概述 为了方便大量数据的输入输出和长期存储,有必要在C语言的程序设计中引入文件的知识。“文件”是指记录在外部介质上的数据的集合,是计算机中数据在存储介质上的存在形式。文件通常分为两大类:程序文件和数据文件。程序文件就是通常所说的可执行文件,是计算机指令和少量数据的集合。数据文件只包含待程序文件处理的数据,通常用来存储大量数据,例如:VCD文件、MP3文件、数据库文件。C语言中的程序通过对文件
2、的读、写等操作来实现对外部存储介质(例如磁盘)上数据的物理操作。通过C语言提供的文件操作函数,可以简单、高效、安全地访问外部数据。1.文件类型文件按其存储数据的格式分为两大类型:文本文件和二进制文件。两种文件格式主要有如下几点区别:1)文本文件由可显示字符组成,如字母、数字、符号;而二进制文件只是若干长度的0、1序列。2)文本文件以字符(8位)为单位写入和读取;二进制文件则以数据块为 单位进行读写。3)文本文件用于存储文字信息,说明文件、C语言源程序文件都是文本文件;二进制文件用于存储非文本数据,如二进制执行代码、图像、声音等。10.1文件概述文件概述 4)文本文件可以直接在屏幕上显示文件内容
3、;二进制文件虽然可以显示,但显示的内容无意义 2.文件类型指针在C语言中引入了文件指针的概念,所有对文件的操作都通过文件指针完成。文件指针类似于C语言中的普通指针,但文件指针不是指向一段内存空间,而是指向一个文件信息结构体,该结构体描述一个文件的相关信息,其定义在stdio.h头文件中。用户无需了解有关此结构体的细节,只需要知道如何使用文件指针即可。v声明一个文件指针使用以下语句:FILE *文件指针名文件指针名 1)要使用文件指针进行文件相关操作必须在程序中包含stdio.h头文件。2)“FILE”全是大写字符,若改成小写字母是错误的。3)声明一个文件指针后,就可以使用各种函数打开、关闭文件
4、以及进行读写操作。C语言中,对文件的基本操作可以说就是文件的打开和关闭、文件的读写等操作。10.2文件的打开与关闭文件的打开与关闭v在实际应用当中,经常要对文件进行处理,C程序对文件的处理过程一般如下:文件的打开。建立一个新的文件或为存取某一个文件的数据而打开文件 对文件进行读、写或其他操作 关闭文件。文件使用完后,要关闭文件,保存文件的改写。1.文件的打开(fopen函数)在C语言中文件的打开库函数来实现,其格式如下:FILE *fp;/*声明一个文件指针声明一个文件指针*/fp=fopen(文件名,打开方式);(文件名,打开方式);文件名:是要求打开文件的文件名(包括扩展名),是一个字符串
5、,以双引号括起。如果省略文件路径,则在当前目录下打开文件。打开放式:有只读、只写、追加、读写几种,使用不同的标识符区分。标识符见表9.110.2文件的打开与关闭文件的打开与关闭打开方式标识符 含义“r”以只读方式打开一个文本文件。“w”以只写方式打开一个文本文件。“a”以追加方式打开一个文本文件。“r+”以读写方式打开一个文本文件。“w+”以读写方式建立一个新的文本文件。“a+”以读写方式建立一个文本文件。“rb”以只读方式打开一个二进制文件。“wb”以只写方式打开一个二进制文件。“ab”以追加方式打开一个二进制文件。“rb+”以读写方式打开一个二进制文件。“wb+”以读写方式建立一个新的二进
6、制文件。“ab+”以读写方式打开一个二进制文件。表9.110.2文件的打开与关闭文件的打开与关闭v例如:fp=fopen(“abc.txt”,”r”)/*以只读方式打开abc.txt文件*/fp=fopen(“abc.c”,”r+”)/*以读写方式打开abc.c文件*/fopen()函数的返回值是一个文件信息结构体的地址,该文件信息结构体是描述目标文件的相关信息。调用fopen()函数前必须声明一个文件指针,并使用文件指针接受fopen()函数的返回值。文件指针被赋值后,程序中就通过这个文件指针对目标文件进行操作。若不使用文件指针接受fopen()函数的返回值,则无法对已打开的文件进行访问,调
7、用fopen()函数也是无意义的。如果不能实现“打开”的任务,fopen函数将会带回一个出错信息。出错的原因可能是用“r”方式打开一个并不存在的文件;磁盘出故障;磁盘已满无法建立新文件等。此时fopen函数将带回一个空指针值NULL(NULL在stdio.h文件中已被定义为0)。v常用下面的方法打开一个文件:if(fp=fopen(“file”,”r”)=NULL)printf(“cannot open this filen”);exit(0);10.2文件的打开与关闭文件的打开与关闭 即先检查打开的操作有否出错,如果有错就在终端上输出“cannot open this file”。Exit函
8、数的作用是关闭所有文件,终止正在调用的过程。待用户检查出错,修改后在运行。2.文件的关闭(fclose函数)使用完一个文件之后应该尽快关闭,以免数据丢失。v关闭一个文件使用fclose()函数实现,其格式如下:Fclose(文件指针文件指针)文件指针:指明要关闭哪个文件,作为参数的文件指针必须是由打开文件函数fopen()得到的。v例如:#include main()FILE*fp;if(fp=fopen(“abc.txt,”“r”)=0)/*尝试打开文件*/10.2文件的打开与关闭文件的打开与关闭 文件打开错误处理 else /*打开文件成功*/读写文件操作 fclose(fp);以上程序由
9、打开文件函数fopen()和关闭文件函数fclose()共同构成了包含文件操作的C语言程序框架。abc.txt是文件名。v应该养成在程序终止之前关闭所有文件的习惯,如果不关闭文件将会丢失数据,因为,在向文件写数据时,是先将数据输到缓冲区,待缓冲区充满后才正式输出给文件。如果当数据未充满缓冲区而程序结束运行,就会将缓冲区中的数据丢失。用fclose函数关闭文件,可以避免这个问题,它先把缓冲区中的数据输出到磁盘文件,然后才在释放文件指针变量。10.3文件的读写文件的读写 对文件来说,读写操作是非常重要的,常用的读写函数如下:10.3.1 fgetc()函数和函数和fputc()函数函数 对文件的操
10、作时一次读写一个字符。1fgetc()函数v从指定的文件读取一个字符,该文件必须是以读或读写方式打开的。其格式如下:char c;c=fgetc(文件指针)v文件指针:指向一个已打开的文件,ch为字符变量。fgetc函数的返回值是一个字符,赋给ch。如果在执行fgetc函数读字符时遇到文件结束符,函数返回一个文件结束标志EOF(-1)。如果想从一个磁盘文件顺序读入字符并在屏幕上显示出来,可以如下操作:ch=fgetc(文件指针);while(ch!=EOF)putchar(ch);ch=fgetc(文件指针);10.3文件的读写文件的读写 注意:EOF不是可输出字符,因此不能在屏幕上显示。由于
11、字符的ASCII码不可能出现-1,因此EOF定义为-1是合适的。当读入的字符值等于-1(即EOF)时,表示读入的已不是正常的字符而是文件结束符。但以上只使用于读文本文件的情况。现在 ANSI C已允许用缓冲文件系统处理二进制文件,而读入某一个字节中的二进制数据的值有可能是-1,而这又恰好是EOF的值。这就出现了需要读入有用数据而却被处理为“文件结束”的情况。为了解决这个问题,ANSI C提供一个feof函数来判断文件是否真的结束。feof(fp)用来测试fp所指向的文件当前状态是否“文件结束”。如果是文件结束,函数feof(fp)的值为1(真),否则为0(假)。v如果读入一个二进制文件中的数据
12、,可以用 while(!feof(fp)c=fgetc(fp);2fputc()函数v把一个字符写到磁盘文件上去,其格式如下:fputc(字符,文件指针);例如向文件指针fp所指的文件写入字符c的语句是:fputc(c,fp);10.3文件的读写文件的读写如果函数调用成功,则返回写入的字符;如果失败,则返回EOF(-1)。下面的程序实现了复制文件的功能,源文件为c:tcabc.txt,目标文件为c:tcxyz.txt。v例10.1 程序举例#include main()FILE*fp1,*fp2;/*声明两个文件指针,分别用于源文件和目标文件*/char c;if(fp1=fopen(abc.
13、txt,r)=NULL|(fp2=fopen(xyz.txt,w+)=NULL)/*同时打开源文件和目标文件,分别为只读方式和新建文件方式*/printf(File Open Errorn);else while(c=fgetc(fp1)!=EOF)/*循环从源文件读入字符,遇到文件结束符停止*/10.3文件的读写文件的读写 fputc(c,fp2);fclose(fp1);fclose(fp2);system(cls);printf(abc.txt:n);system(type abc.txt);/*调用DOS命令输出源文件内容*/printf(nnxyz.txt:n);system(typ
14、e xyz.txt);/*调用DOS命令输出目标文件内容*/v运行结果如下:10.3文件的读写文件的读写10.3.2 fgets()函数和函数和fputs()函数函数 以字符为单位的fgetc()函数和fputc()函数一次只能读出或写入一个字符到文件中,显然处理大量数据时效率不高,以字符串为单位的fgets()函数和fputs()函数可以一次从文件输入或向文件输出一个字符串。1fgets()函数vfgets()是从文件而不是从标准输入设备取得字符串。其格式如下:fgets(字符串指针,字符个数,文件指针字符串指针,字符个数,文件指针);其中第一个参数“字符串指针”,即一个字符组名或指向字符的
15、指针,用于存放读出的字符串;第二个参数指明读出多少个字符,是一个整型数;第三个参数即目标文件的文件指针。fgets()在遇到换行符或文件结束符时,即使已读取得字符数小于参数中指定的数量也会自动停止。如程序设计者已经知道abc.txt文件不大于100个字节,调用fgets()函数的第二个参数为100,使得整个文件被一次读取。若abc.txt文件大于100字节,则后面的内容没有被读取。如果fgets()读取到文件结束符,将会返回一个NULL值。可以据此判断是否到达文件尾部,使用循环语句读出整个文件。若目标文件的结构不清晰,一般使用fgetc()函数逐个字符读取,逐个处理。在预先知道目标文件结构的情
16、况下,使用fgets()函数能提高效率。10.3文件的读写文件的读写2fputs()函数vfputs()函数用于向文件写入字符串,它的使用格式如下:fputs(字符串,文件指针字符串,文件指针);第一个参数可以是一个字符串,也可以是一个字符数组或指向字符的指针;第二个参数是文件指针。v例如:char c100;char*s;fputs(“Hello”,fp);/*将字符串“Hello”写到fp所指文件中 */fputs(*s,fp);/*将字符指针s所指的字符串写到fp所 指文件中*/fputs(c,fp);/*将字符数组c的内容写到fp所指文件中*/v下面的程序利用fgets()函数和fputs()函数实现了复制文件的功能,源文件为abc.txt,目标文件为xyz.txt。10.3文件的读写文件的读写v例10.2 程序举例#include main()FILE*fp1,*fp2;char s100;if(fp1=fopen(abc.txt,r)=NULL|(fp2=fopen(xyz.txt,w+)=NULL)printf(File Open Errorn);else fgets(s