1、2018/3/29,1,C语言程序设计,第8章 文 件,2018/3/29,2,【本章概要】,本章主要介绍文件的概念及其相关操作等内容,其中包括用文件指针进行文件打开、关闭和读写操作等。通过本章学习,要求了解磁盘文件的概念和用途;掌握文件指针的概念和文件变量的定义方法;深刻理解文件的读、写等基本操作的实现;熟悉文件的打开、关闭、读、写等函数的调用形式;掌握文件操作在程序设计中的应用方法。,2018/3/29,3,8.1 文件概述,8.2 文件的打开与关闭,8.3 文件的读写,第1章 C语言程序设计基础,2018/3/29,4,程序在实现过程中,运行程序所需要的数据是通过键盘输入的,程序运行的结
2、果只显示在屏幕上。当一个程序运行完成或终止运行,所有的变量的值不再保存。 文件是解决上述问题的有效方法,它通过把数据存储在磁盘文件中,得以长久保存。当有大量数据输入时,可通过编辑工具事先建立输入数据的文件,程序运行时从指定文件读入,从而实现数据一次输入多次使用。同样,当有大量数据输出时,可以将其输出到指定的文件,并且任何时候都可以查看结果文件。一个程序的运算结果还可以作为另外程序的输入,进行进一步加工。,8.1 文件概述,2018/3/29,5,所谓“文件”是指一组相关数据的有序集合。这个数据集有一个名称,叫做文件名。 在前面的章节中我们已经多次使用了文件,例如源程序文件(.c)、目标文件(.
3、obj)、可执行文件(.exe)等。它们通常驻留在外部介质(如磁盘)上,在使用时才调入内存。下面我们从不同的角度对文件作不同的分类。,8.1 文件概述,8.1.1 文件的概念,2018/3/29,6,1. 从用户使用的角度看 文件可分为普通文件和设备文件两种。 普通文件是指驻留在磁盘或其它外部介质上的一个有序数据集,可以是源文件、目标文件、可执行程序,也可以是一组待输入处理的原始数据,或者是一组输出的结果。 设备文件是指与主机相连的各种外部设备,如显示器、打印机、键盘等。在操作系统中,把外部设备也看作是一个文件来进行管理,把它们的输入和输出等同于对磁盘文件的读和写。通常把显示器定义为标准输出文
4、件,一般情况下在屏幕上显示有关信息就是向标准输出文件输出。,8.1 文件概述,8.1.1 文件的概念,2018/3/29,7,2. 从文件编码和数据的组织方式来看 文件可分为ASCII码文件和二进制码文件。 ASCII文件也称为文本文件,这种文件在磁盘中存放时每个字符占一个字节,每个字节中存放相应字符的ASCII码,内存中的数据存储时需要转换为ASCII码。 二进制文件是按二进制的编码方式来存放文件的,内存中的数据存储时不需要进行数据转换,存储介质上保存的数据采用与内存数据一致的表示形式存储。,8.1 文件概述,8.1.1 文件的概念,2018/3/29,8,在C语言程序中,无论是一股磁盘文件
5、还是设备文件,都可以通过文件结构类型的数据集合进行输入输出操作。文件结构是由系统定义的,取名为FILE。FILE结构是用typedef语句定义出的一种类型,并且这个结构实现已经被定义在stdio.h头文件中,使用文件程序都需要包含“#include”。 C语言中,用一个指针变量指向一个文件,这个指针称为文件指针。通过文件指针就可对它所指的文件进行各种操作。定义说明文件指针的一般形式为: FILE *指针变量标识符,8.1 文件概述,8.1.2 文件指针,2018/3/29,9,任何一个文件在使用之前要进行打开操作,使用之后关闭操作。 这是因为操作系统对于同时打开的文件数目是有限制的,DOS操作
6、系统中,可以在DEVICE.SYS中定义允许同时打开的文件数n(用files=n定义)。其中n 为可同时打开的文件数,一般n=20。因此在使用文件前应打开文件,才可对其中的信息进行存取。用完之后需要关闭,否则将会出现一些意想不到的错误。所以对磁盘文件操作时,一定要养成“先打开,后读写操作,最后关闭”的习惯。,8.2 文件的打开与关闭,2018/3/29,10,C语言用fopen()函数来实现文件的打开。fopen函数的调用方式一般为: FILE *fp; fp=fopen(文件名,文件使用方式); fopen()函数中第一个形式参数可以包含路径和文件名两部分。 例如:fp=fopen(“c:t
7、cin.txt”;“r”);,8.2 文件的打开与关闭,8.2.1 文件的打开操作,2018/3/29,11,C语言用fopen()函数来实现文件的打开。fopen函数的调用方式一般为: FILE *fp; fp=fopen(文件名,文件使用方式); fopen()函数中第一个形式参数可以包含路径和文件名两部分。 例如:fp=fopen(“c:tcin.txt”;“r”);,8.2 文件的打开与关闭,8.2.1 文件的打开操作,2018/3/29,12,文件打开方式,8.2 文件的打开与关闭,8.2.1 文件的打开操作,2018/3/29,13,如果成功的打开一个文件,fopen()函数返回文
8、件指针,否则返回空指针(NULL)。由此可判断文件打开是否成功。例如: if (fp=fopen (“c:tcint.txt, r)=NULL) printf(“Cannot open this file.n”);exit(0); 如果屏幕上显示“Cannot open this file.”,则表明打开文件出错。出错的常见原因是:用“r”方式打开一个不存在的文件。exit函数的作用是关闭所有文件,终止正调用的过程。待程序员检查出错误,修改后再运行。,8.2 文件的打开与关闭,8.2.1 文件的打开操作,2018/3/29,14,【说明】(1)用“w”方式打开文件时,只能从内存向该文件输出(写
9、)数据,而不能从文件向内存输入数据。如果该文件原来不存在,则打开时按指定文件名建立一个新文件。如果原来的文件已经存在,则打开时将文件删空,然后重新建立一个新文件。(2)用“a”方式打开文件时,向文件的尾部添加新数据,文件中原来的数据保留,但要求文件必须存在,否则会返回出错信息。打开文件时,文件的位置指针在文件末尾。,8.2 文件的打开与关闭,8.2.1 文件的打开操作,2018/3/29,15,【说明】(3)用“r +”、“w+”、“a+”方式打开文件时,既可以输入也可以输出,不过三种方式是有区别的;“r+”方式要求必须文件存在;“w+”方式则建立新文件后进行读写;“a+”方式则保留文件原有的
10、数据,进行追加或读的操作。(4)在用文本文件向计算机输入时,应将回车和换行两个字符转换为一个换行符;在输出时,应将换行符转换为回车和换行两个字符。在用二进制文件时,不需进行这种转换,因为在内存中的数据形式与输出到外部文件中的数据形式完全一致,一一对应。,8.2 文件的打开与关闭,8.2.1 文件的打开操作,2018/3/29,16,文件在使用完后应该及时关闭它,以防止它再被误用。“关闭”就是释放文件指针。释放后的文件指针变量不再指向该文件,为自由的文件指针。这种方式可以避免文件中的数据丢失。释放指针后不能再通过该指针对原对应的文件进行读写操作,除非再次用该指针变量打开该文件。 用fclose函
11、数关闭文件,fclose函数调用的一般形式为: fclose(文件指针);,8.2 文件的打开与关闭,8.2.2 文件的关闭操作,2018/3/29,17,文件在使用完后应该及时关闭它,以防止它再被误用。“关闭”就是释放文件指针。释放后的文件指针变量不再指向该文件,为自由的文件指针。这种方式可以避免文件中的数据丢失。释放指针后不能再通过该指针对原对应的文件进行读写操作,除非再次用该指针变量打开该文件。 用fclose函数关闭文件,fclose函数调用的一般形式为: fclose(文件指针);,8.2 文件的打开与关闭,8.2.2 文件的关闭操作,2018/3/29,18,例如: fclose(
12、fp); 用fopen()函数打开文件时所带回的指针赋给了fp,现把该文件关闭。如果文件关闭成功,fclose函数返回值为0;如果关闭出错,则返回值为EOF(-1)。这可以用ferror函数来测试,当然也可以根据函数的返回值自己编程判断文件是否关闭成功。,8.2 文件的打开与关闭,8.2.2 文件的关闭操作,2018/3/29,19,文件的读和写是最常用的文件操作,C语言提供了多种文件读写函数: 文件字符读/写函数: fgetc和fputc 文件字符串读/写函数: fgets和fputs 文件格式化读/写函数: fscanf和fprintf,8.3 文件的读写,2018/3/29,20,1.
13、字符输入函数fgetc 从指定文件读入一个字符,该文件必须是以读或读写方式打开的。 fgetc函数的调用形式为: 字符变量=fgetc(文件指针);例如,从fp指向的文件中读取一个字符并赋给字符变量ch,则可写成: ch=fgetc(fp);,8.3 文件的读写,8.3.1文件字符读/写,2018/3/29,21,【说明】(1)fgetc为字符读函数,因此之前必须以读或读写方式打开文件;(2)在执行fgetc读字符时遇到文件结束符或出错,则函数返回一个文件结束标志EOF(-1)。当形参fp为标准输入文件指针stdin时,则读文件字符函数fgetc(stdin)与终端输入函数getchar()具
14、有完全相同的功能。,8.3 文件的读写,8.3.1文件字符读/写,2018/3/29,22,【例8-1】在屏幕上显示文本文件readme.txt的内容。#include “stdio.h”main() FILE *fp; char ch; if(fp=fopen(readme.txt,r)=NULL) printf(file open error.n); exit(0); while(ch=fgetc(fp)!=EOF) putchar(ch); fclose(fp); ,8.3 文件的读写,8.3.1文件字符读/写,2018/3/29,23,2. 字符输出函数fputc fputc函数把一个
15、字符写入到磁盘文件中。其一般形式为: fputc(字符变量,文件指针); 同样,fputc(ch,stdout)的作用是将字符变量ch的值在显示器上输出,与函数putchar(ch)的功能完全相同。,8.3 文件的读写,8.3.1文件字符读/写,2018/3/29,24,【例8-2】从键盘上输入一行字符,写入“test.txt”文件中。#include stdio.hmain() FILE *fp; char ch; if(fp=fopen(test.txt,w)=NULL) printf(file created error.n); exit(0); printf(“Input a stri
16、ng(ENTER for end input)n”); while(ch=getchar()!=n) fputc(ch,fp); fclose(fp); ,8.3 文件的读写,8.3.1文件字符读/写,2018/3/29,25,1. 读文件字符串函数fgets 从指定文件读入一个字符串,该文件必须是以读或读写方式打开的。fgets()函数的调用形式为: fgets(str,n,fp); 功能为从fp指向的文件读取至多n-1个字符(n用来指定字符数),并把它们放到字符数组str中。在读入之后自动向字符串未尾加上串结束标志0。如果读成功返回str数组首地址,失败返回一个空指针。读取操作遇到以下情况
17、结束: 已经读取了n-1个字符; 在读出n-1个字符之前,当前读取到的字符为回车符或者文件未尾。,8.3 文件的读写,8.3.2文件的字符串读/写,2018/3/29,26,2. 写文件字符串函数fputs fputs函数把一个字符串写入到磁盘文件上。其一般形式为: fputs(str,fp); 功能为把字符串str写入到fp所指向的文件,但字符串结束符0不写入。,8.3 文件的读写,8.3.2文件的字符串读/写,2018/3/29,27,【例8-4】利用字符串读写函数编程实现例8-3功能,即将readme.txt复制到result.txt中。同时,将readme.txt文件内容显示在屏幕上。
18、#include “stdio.h”main() FILE *fp1,*fp2; char str20; if(fp1=fopen(readme.txt,r)=NULL) printf(file1 openned error.n); exit(0); if(fp2=fopen(result.txt,w)=NULL) printf(file2 created error.n); exit(0); while(fgets(str,20,fp1)!= NULL) fputs(str,fp2); printf(“%s”,str); fclose(fp1); fclose(fp2);,8.3 文件的读写
19、,8.3.2文件的字符串读/写,2018/3/29,28,1. 格式化输入函数fscanf 函数调用的格式为: fscanf(fp,格式控制串,输入列表); 其中,fp是指向要读取文件的文件型指针,格式控制串,输入列表同scanf函数。 功能是从fp指向的文件中,按格式控制串中的控制符读取相应数据赋给输入列表中对应的变量。例如: fscanf(fp,%d,%f, 该语句完成从指定的磁盘文件中读取ASCII字符,并按%d和%f格式转换成二进制形式的数据给变量a,f。,8.3 文件的读写,8.3.3文件格式化读/写,2018/3/29,29,2. 格式化输出函数fprintf 函数调用的格式为:
20、fprintf(fp,格式控制串,输出列表); 其中,fp是指向要写入文件的文件型指针,格式控制串,输出列表同printf函数。 功能是将输出列表中的各个变量或常量,依次按格式控制串中的控制符说明的格式写入fp指向的文件中。,8.3 文件的读写,8.3.3文件格式化读/写,2018/3/29,30,【例8-5】 格式化函数示例。#include”stdio.h” main() char *s=Thats good news;int i=627;FILE *fp; fp=fopen(test.txt, w); fputs(Your score of TOEFL is , fp); fputc(:
21、, fp);fprintf(fp, %dn, i);fprintf(fp, %s, s);fclose(fp); ,8.3 文件的读写,8.3.3文件格式化读/写,2018/3/29,31,1. 文件结束判断feof()函数 feof()函数的调用格式为: feof(文件指针); feof()函数检测文件位置指针是否到达了文件结尾,若是则返回一个非0值,否则返回0。这个函数对二进制文件操作特别有用,因为二进制文件中,文件结尾标志EOF也是一个合法的二进制数,只简单的检查读入字符的值来判断文件是否结束是不行的。如果那样的话, 可能会造成文件未结尾而被认为结尾,所以就必须有feof()函数。,8.
22、3 文件的读写,8.3.4其它相关函数,2018/3/29,32,2. rewind()函数 rewind()函数的调用形式为: rewind(文件指针); 功能是使文件内部的位置指针指到文件的开头,此函数没有返回值。,8.3 文件的读写,8.3.4其它相关函数,2018/3/29,33,3. fseek()函数 fseek()函数的调用形式为: fseek(fp,offset,fromwhere); 其中,fp是文件指针。offset为文件位置指针的位移量,指以起始位置为基准值向前移动的字节数,它是一个长整型量,如果它的值为负数,表示向后移,即向文件头方向移动。fromwhere表示文件位置
23、指针起始计算位置,位置可取3种值:文件首部、当前位置和文件尾部,实际表示时分别对应值0、1、2,或常量SEEK_SET、SEEK_CUR、SEEK_END。,8.3 文件的读写,8.3.4其它相关函数,2018/3/29,34,【注意】fseek()函数一般用于对二进制文件进行操作。 下面是fseek函数调用的几个例子: fseek(fp,100L,0); /*将位置指针移到离文件头100个字节处*/ fseek(fp,50L,1); /*将位置指针移到离当前位置50个字节处*/ fseek(fp,-20L,2); /*将位置指针从文件末尾处向后退20个字节*/ 注意偏移量为长整型,如100L
24、。,8.3 文件的读写,8.3.4其它相关函数,2018/3/29,35,4. ftell( )函数 ftell()函数的作用是得到文件中位置指针的当前位置。如果ftell()函数返回值为-1L,则表示出错。例如: if(ftell(fp)=-1L) printf(errorn);,8.3 文件的读写,8.3.4其它相关函数,2018/3/29,36,5. 文件读写错误检测ferror( )函数 在调用各种输入输出函数(如fputc、fgetc、fread、fwrite等)时,如果出现错误,则除了函数返回值有所反映外,还可以用ferror函数检查,它的一般调用形式为: ferror(fp);
25、如果ferror返回值为0(假),则表示未出错。如果返回一个非0值,则表示出错。应该注意,对同一个文件,每一次调用输入输出函数,均产生一个新的ferror函数值,因此,应当在调用一个输入输出函数后立即检查ferror函数的值,否则信息会丢失。 在执行fopen函数时,ferror函数的初始值自动置为0。,8.3 文件的读写,8.3.4其它相关函数,2018/3/29,37,6. 清除文件错误标志clearerr( )函数 clearerr函数的作用是使文件错误标志和文件结束标志置为0。假设在调用一个输入输出函数时出现错误,ferror函数值为一个非0值。在调用clearerr(fp)后,fer
26、ror(fp)的值变成0。 只要出现错误标志,就一直保留,直到对同一文件调用clearerr函数或rewind函数,或任何其它一个输入输出函数。,8.3 文件的读写,8.3.4其它相关函数,2018/3/29,38,文件操作是程序设计中的一个重要内容,C语言把文件看作为”字节流”,通过文件指针指向这个”字节流”,采用系统提供的函数对文件进行读、写、定位等操作。 文件的操作有3大步骤:打开文件、读写文件和关闭文件。文件一旦被打开,就自动地在内存中建立该文件的FILE结构,且可同时打开多个文件。对文件的读写操作都是通过库函数实现的。这次库函数最好配合使用,避免引起一些读、写混乱。,【本章小结】,2018/3/29,39,第8章 作业,一、二、三,