1、第十章 文 件,C文件的有关概念,10.1,文件是一组存储在外存储设备上的数据的集合。,1 什么是文件,操作系统是以文件为单位对数据进行管理的。 输入输出是数据传送的过程,数据如流水一样从一处流向另一处,因此常将输入输出形象地称为流(stream),即输入输出流。 语言把文件看作是一个字符(字节)的序列,即文件是由一个一个字符(字节)的数据顺序组成。 一个输入输出流就是一个字节流或二进制流。,保存和交换数据。 保存大容量数据。,3 文件的分类:,数据表示方式:,二进制文件。 文本文件(ASCII)文件。,读写方式:,顺序读写文件(流式)。 随机读写文件。,处理方法:,缓冲文件。 非缓冲文件。,
2、Device,内存,Buffer,匹配主机速度,数据转换。,2 文件的优点:,文件的操作过程,打开文件,建立一个文件和流的对应关系。在内 存中建立一个保存文件信息的结构变量。,读写文件,关闭文件,释放文件所占的资源。,10.2 文件的操作过程与文件指针,文件指针(File Pointer),在缓冲文件系统中,每个被使用的文件的信息(如文件名、位置、类型等)都保存在一个特殊定义的结构体类型的指针变量中。该结构体类型由用户定义,名为:FILE,可以定义一个指向FILE类型的结构体指针,打开文件是让该指针指向文件对应的结构变量,通过该指针对文件进行操作。,FILE *fp; fp是FILE型指针变量
3、 fp标识一个特定的磁盘文件,typedef struct short level; /*缓冲区满或空的程度*/unsigned flags; /*文件状态标志*/char fd; /*文件描述符*/unsigned char hold; /*如无缓冲区不读字符*/short bsize; /*缓冲区的大小*/unsigned char *buffer;/*数据缓冲区的位置*/unsigned char *curp; /*指针当前的指向*/unsigned istemp; /*临时文件指示器*/short token; /*用于有效性检查*/FILE; 在stdio.h文件中定义,3 文件读写
4、的方式,文件按读写方式可以分为: 顺序读写 随机读写,顺序读写:顺序向后读写。,随机读写:给定位置读写。,10.3 文件的打开与关闭,文件的打开函数 fopen( ),fopen函数的原型在stdio.h文件中说明,该函数的作用是打开缓冲文件。,使用方法:,FILE *fp ; fp = fopen( filename , mode ) ;,打开文件的文件名或设备名。,文件的读写方式。,文件信息结构的指针。,fp=fopen(“a:wang.dat”,”w+”);,说明:,如果fopen失败,则函数返回空指针NULL;,当文件打开错误时,程序不应继续执行,一般以如下方式打 开文件:,if (
5、fp=fopen( filename , mode ) =NULL ) printf ( “File Open Error! n” ) ;exit (1) ;,文件的读写方式说明:,文件的关闭函数fclose(),文件使用完必须关闭,关闭文件的目的是:,保证文件的数据不丢失,将buffer的数据回写文件。,释放buffer。,关闭文件函数的使用:,fclose(文件指针);,FILE *fp; fp=fopen(“a:d.dat”,”w+”); /* 文件的读写 */ fclose(fp);,说明:,如果关闭正确fclose返回0;关闭失败fclose 返回非0。,10.4 文件的顺序读写,文
6、件的读写是由定义在stdio.h中的一组函数的集合所实现的。,字符输入和输出函数 fputc函数和fgetc函数, fputc函数,使用方法:fputc (ch , fp ) ;,含 义:将字符ch写入文件指针对应的文件的当前位置。,返回值:写入正确返回ch的值;失败返回EOF( 在stdio.h中定 义为-1)。, fgetc函数,使用方法:ch = fgetc ( fp ) ; /*ch为字符型变量。*/,含义:从文件指针fp对应的可读文件的当前位置读一个字符返 回赋值给ch。, feof 函数,使用方法:i=feof (fp) ;,含 义:判断文件是否结束。,返回值:1 代表文件结束;0
7、 代表文件未结束。,【例10-1】从键盘输入10个字符,写入文件f2.txt中。,#include #include void main(void) int i; char ch;FILE *fp; /* 定义文件指针 */if(fp=fopen(“c:f2.txt”,“w”)= NULL) /* 以写方式打开文件 */ printf(“File open error!n“);exit(1); /* 无法打开则结束 */for(i=1;i=10;i+) /* 循环10次 */ ch = getchar(); /* 从键盘输入字符 */fputc(ch,fp); /* 将字符写入文件 */if(
8、 fclose(fp) /* 关闭文件 */ printf(“File close error!n“);exit(1); /* 无法关闭则结束 */ ,#include #include void main(void) int i; char ch;FILE *fp; /* 定义文件指针 */if(fp=fopen(“f1.txt“,“w“)= NULL) /* 以写方式打开文件 */ printf(“File open error!n“);exit(1); /* 无法打开则结束 */for(i=1;i=10;i+) /* 循环10次 */ ch = getchar(); /* 从键盘输入字符
9、 */fputc(ch,fp); /* 将字符写入文件 */if( fclose(fp) /* 关闭文件 */ printf(“File close error!n“);exit(1); /* 无法关闭则结束 */,【例10-2】从键盘输入10个字符,写入文件f1.txt中,再从此文件中读出字符显示在屏幕上。,If (fp=fopen(“f1.txt”,“r”) = NULL) /*再次打开文件以读方式*/printf(“File open error!n“);exit(1); for(i=1;i=10;i+)ch = fgetc(fp); /* 从文件读入字符 */putchar(ch);
10、/* 将字符输出到屏幕 */if( fclose(fp) /* 关闭文件 */printf(“File close error!n“);exit(1); ,#include #include void main(void) char ch;FILE *fin,*fout; /* 定义文件指针 */if(fin=fopen(“c:f1.txt”,“r”) = NULL) /* 以读方式打开文件 */ printf(“File open error!n“);exit(1); if(fout=fopen(“c:f4.txt“,“w“)= NULL)/* 以写方式打开文件 */ printf(“Fil
11、e open error!n“);exit(1); /* 无法打开则结束 */,【例10-3】将磁盘文件f1.txt中的内容复制到另一个文件f4.txt中。,while(ch=fgetc(fin)!=EOF) fputc(ch,fout); /* 从文件fin读出字符写入文件fout */if(fclose(fin) /* 关闭文件 */printf(“File close error!n“);exit(1); /* 无法关闭则结束 */if(fclose(fout) /* 关闭文件 */printf(“File close error!n“);exit(1); /* 无法关闭则结束 */ ,
12、文件中字符串的输入和输出函数,字符串输入函数,使用方法:fgets(str , n , fp);,含 义:从fp所对应的文件的当前位置读n-1 个字符到str所指向的内存单元。并在结束处加0表示字符串结束。,三种情况可以使输入结束: 读完n-1个字符; 读出时遇到n; 读出时遇到文件结束标志。,字符串输出函数,使用方法:fputs(str , fp);,含 义:将str指向的字符串,输出到fp所对应的文件中,并忽略输出字符串结束标志0。,#include #include #define SIZE 256 void main ( int argc , char *argc ) char buf
13、fSIZE ;FILE *fpr,*fpw ;fpw=stdprn ;if( fpr = fopen ( argc1 , “r” ) = NULL ) printf ( “File open error!n ” ) ;exit (0) ; while (fgets (buff , SIZE , fpr) != NULL )fputs (buff , fpw ) ; fclose (fpr) ; ,打开文件,输入。,输出到打印机。,文件指针执行设备: stdprn 打印机;stdaux 串口; stdin、stdout。,举例:从文件中读出字符串,并输出其内容到屏幕。,#include #inc
14、lude void main(void) char ch80;FILE *fin,*fout; /* 定义文件指针 */if(fin=fopen(“e:f5.txt“,“r“) = NULL) /* 以读方式打开文件 */ printf(“File open error!n“);exit(1); if(fout=fopen(“f6.txt“,“w“)= NULL) /* 以写方式打开文件 */ printf(“File open error!n“);exit(1); /* 无法打开则结束 */,【例10-4】利用字符串输入输出函数将一个磁盘文件中的内容f5.txt复制到另一个文件f6.txt中
15、。,while( !feof(fin) fgets(ch,80,fin); /* 从文件fin读出字符*/fputs(ch,fout); /* 写入文件fout */if( fclose(fin) /* 关闭文件 */printf(“File close error!n“);exit(1); /* 无法关闭则结束 */if(fclose(fout) /* 关闭文件 */printf(“File close error!n“);exit(1); /* 无法关闭则结束 */ ,文件的格式化输入和输出函数,fp文件指针 format ,格式说明字符串,取%d、%x、%f、%c等;说明输入转化的格式。
16、 &arg1&argn,接收读出数据的变量的地址列表。, 格式化输入函数 fscanf,使用方法:fscanf (fp , format , ,含义:从fp对应的文件的当前位置,顺序读出一个字符序列, 按format说明的格式和类型进行转换并存放到对应变量单元。,#include #include void main (void) char s80 ;int a ;FILE *fp ;if ( fp=fopen ( “e:text.txt” , “r” ) = NULL) printf (“cannot open file “ ) ;exit (0) ;fscanf ( fp , “%s %d
17、 “ , s , ,打开文件,读出数据。,例10-5:从text.txt中读字符串和一个十进制数,输出到显示器。,fp文件指针; format ,格式说明字符串,取%d、%x、%f、%c等;说明输出转化的格式。 arg1argn,输出量列表。,使用方法: fprintf ( fp , format , arg1, arg n ) ;,含义: 以指定的格式(format),将arg1arg n的值,写入fp 文件的当前位置。,FILE *fp; fp=fopen(“s.dat”,”w”); fprint(fp,”%d%c”,123,c); fclose(fp);,格式化输出函数 fprintf,
18、文件的数据块输入输出函数,buf(空类型指针)接收数据的地址; size(整型)一次读取数据的字节数; count(整型)读取次数; fp对应输入文件的文件指针。, fread( )函数,使用方法:fread(buf,size,count,fp);,含义:从 fp 指向的文件的当前位置,每次读取size个字节,共 读count 次数据,存放到buf指向的内存处。,返回值:,调用正确,返回输入的项数;,调用错误,返回-1(EOF)。,FILE *fp; char str80; fp=fopen(“s.dat”,”r”); fread(str,20,3,fp);,#include #include
19、 void main(void) int i;float score,aver = 0;FILE *fin,*fout; /* 定义文件指针 */if(fin=fopen(“e:f7.txt”,“r”) = NULL) /* 以读方式打开文件 */printf(“File open error!n“);exit(1); if(fout=fopen(“f8.txt“,“w“)= NULL) /* 以写方式打开文件 */printf(“File open error!n“); exit(1); for(i=0;i10;i+) /* 读源文件中的数据 */,【例10-6】读入磁盘文件f7.txt中存
20、放的10个学生的数学成绩,然后求出它们的平均成绩,并将平均成绩写入文件f8.txt。,fscanf(fin,“%f“, , fwrite函数,buf(空类型指针)数据的地址; size(整型)一次输出数据的字节数; count(整型)输出次数; fp对应输出文件的文件指针。,使用方法:fwrite(buf,size,count,fp);,含义:从buf 开始,分count次,每次size个字节,向fp对应文 件的当前位置写数据。,返回值:,调用正确时,返回 count。,调用错误时,返回 -1(EOF)。,举例:,#include #include void main(void) FILE *
21、stream;char msg = “This is a test“,buf20;stream = fopen(“TEST1.DAT“, “w+“);fwrite(msg, strlen(msg)+1, 1, stream);fseek(stream, SEEK_SET, 0);fread(buf, strlen(msg)+1, 1, stream);printf(“%sn“, buf);fclose(stream); ,打开文件。,写数据到文件。,重新定位到文件头。,#include #include struct stud char name20;float score; studmes3
22、; /* 定义结构 */ void main(void) int i;char strTemp20;FILE *fout; /* 定义文件指针 */if(fout=fopen(“f9.dat“,“wb“) = NULL) /* 以写方式打开文件 */printf(“File open error!n“);exit(1); ,【例10-7】首先生成磁盘文件f9.dat,在其中存放3个学生的姓名和数学成绩,并读出磁盘文件中的内容,显示在屏幕上。,for(i=0;i3;i+)gets(studmesi.name); /* 输入姓名 */gets(strTemp); /* 输入成绩 */studmes
23、i.score = (float)atof(strTemp); /* 转换为数值 */fwrite( ,if(fout=fopen(“f9.dat”,“rb”)= NULL) /* 以读方式打开文件 */printf(“File open error!n“); exit(1); for(i=0;i3;i+)fread( ,5.整数输入输出函数getw函数和putw函数,(1)整数输入函数getw(),使用方法: int a;a = getw(fp);,功能:从文件指针fp指向的文件中读取一个整数,该函数只适合于二进制文件。,(2)整数输出函数putw(),使用方法: putw(a , fp);
24、,功能:将整数a写入文件指针fp指向的文件中,该函数只适合于二进制文件。,#include #include void main(void) int i,a;FILE *fout; /* 定义文件指针 */if(fout=fopen(“f10.dat“,“wb+“) = NULL) /* 以写方式打开文件 */printf(“File open error!n“); exit(1); for(i=0;i10;i+)scanf(“%d”, /* 写入文件 */if(fclose(fout) /* 关闭文件 */,【例10-8】将10个整数写入文件f10.dat中,并读出其内容显示在屏幕上。,pr
25、intf(“File close error!n“);exit(1); if(fout=fopen(“f10.dat“,“rb“)= NULL) /* 以读方式打开文件 */printf(“File open error!n“); exit(1); for(i=0;i10;i+)a = getw(fout); /* 读出文件 */printf(“%d, “,a); /* 显示在屏幕上 */if(fclose(fout) /* 关闭文件 */printf(“File close error!n“);exit(1); ,10.4 文件的随机读写与定位,以上的所有文件的读写都是顺序的,完成一次读写操
26、作后,文 件的记录位置自动指向下一位置,因而称为顺序的流式文件。用户想使用任意位置的读写,可以通过定位函数实现。,获取文件当前位置 ftell函数,long n; n=ftell(fp);,含义:获取文件当前的读写位置(从文件头到当前的字节数)。,返回值(long):,调用正确,返回当前位置相对于文件开头的字节数;,调用错误,返回 -1L。, 改变文件指针的当前位置 fseek函数,fp文件指针; offset(long int),以from为起点移动的偏移量(字节数); from为移动的起始位置。,使用方法: fseek( fp , offset , from) ;,from 在stdio.
27、h中定义了如下常量:,fseek( fp , 50L, SEEK_SET),移到距fp对应文件开始50字节处。,置文件指针于开头位置 rewind( ) 函数,使用方法: rewind(fp);,#include #include void main(void) int i;int score;FILE *fin; /* 定义文件指针 */if(fin=fopen(“f11.dat“,“r“) = NULL)/* 以读方式打开文件 */printf(“File open error!n“);exit(1); for(i=0;i10;i+) fscanf(fin,“%d”, /* 显示在屏幕上
28、*/,【例10-9】已知数据文件f11.txt中含有10个整型数据,依次读出数据显示在屏幕上,再将下标为奇数的数据读出显示在屏幕上。,rewind(fin); /* 将文件指针定位在首部 */printf(“n“); for(i=0;i5;i+) /* 读源文件中的数据 */fseek(fin,sizeof(int),1); /* 将文件指针向后移动 */fscanf(fin,“%d“, ,#include #include #define N 30 struct student char name10 ;int no ;int score ; stud N ; void main (void
29、 ) int i;FILE *fp ;fp=fopen(“std.lst” , “rb” );for ( i=0 ; iN ; i+) fseek ( fp, i*sizeof( struct student ) , 0 ) ;fread ( ,举例:已知30 个学生的一门课的分数,打印 学号为单号学生的分数。,10.5 文件的错误检测,文件读写错误检测函数 ferror。,使用方法:ferror(fp);,含 义:检测文件读写错误。,如果返回值为0,表示无错误。,如果返回值非0,表示有错误。,该标志一旦置位,必须通过清除函数清除!,清除文件错误标志函数 clearerr,使用方法:clear
30、err(fp);,含 义:清除文件读写错误标志。,举例:,#include void main(void) FILE *stream;stream = fopen(“DUMMY.FIL“, “w“);(void) getc(stream);if (ferror(stream)printf(“Error reading from DUMMY.FILn“);clearerr(stream);fclose(stream); ,/* example 9-9 文件的错误检测函数 */ #include #include void main(void) FILE *fp; /* 定义文件指针 */if(f
31、p=fopen(“f2.txt“,“r“)= NULL) /* 以读方式打开文件 */printf(“File open error!n“); exit(1); fgetc(fp); /* 读文件 */printf(“%d”,ferror(fp); /* 显示错误信息 */if(fclose(fp) /* 关闭文件 */,【例9-9】文件出错函数应用。,printf(“File close error!n“); exit(1); printf(“n“);if(fp=fopen(“f2.txt“,“w“)= NULL) /* 以写方式打开文件 */printf(“File open error!
32、n“); exit(1); fgetc(fp); /* 读文件 */printf(“%d“,ferror(fp); /* 显示错误信息 */if(fclose(fp) /* 关闭文件 */printf(“File close error!n“); exit(1);printf(“n“); ,9.6 文件程序设计应用,/* example 9-10 查找三角函数sin(x)的值 */ #include #include #include #define PI 3.1415926 void main(void) int i;double fvalue;FILE *fp; /* 定义文件指针 */i
33、f(fp=fopen(“sin.dat“,“wb+“) = NULL) /* 打开文件 */printf(“File open error!n“);exit(1); for(i=0;i360;i+),【例9-9】文件出错函数应用。,fvalue = sin(PI*i/180.); /* 计算三角函数的值 */fwrite( /* 关闭文件 */ ,/* example 9-11 字符串的处理 */ #include #include void main(void) char str80;int i,m,n;FILE *fp1,*fp2; /* 定义文件指针 */if(fp1=fopen(“st
34、r.txt“,“r“) = NULL) /* 以读方式打开文件 */printf(“File open error!n“);exit(1); ,【例10-11】已知文件str.txt中存放了一串字符,如:abcdefghijklmn,文件val.txt中存放了2个整数m和n,如:3和4,读出这2个文件中的数据,从字符串中的第m个字符开始,取出n个字符,如:cdef,追加在文件str.txt中,得到:abcdefghijklmncdef。,if(fp2=fopen(“val.txt”,“r”) = NULL) /* 以读方式打开文件 */printf(“File open error!n“);e
35、xit(1); fscanf(fp1,“%s”,str); /* 读字符串 */fscanf(fp2,“%d%d”, ,if(fp1=fopen(“str.txt“,“a“) = NULL) /* 以追加方式打开文件 */printf(“File open error!n“);exit(1); for(i=m;im+n;i+) fputc(stri-1,fp1); /* 追加数据 */if(fclose(fp1) /* 关闭文件 */printf(“File close error!n“);exit(1); ,根据数据的组织形式,数据文件可分为ASCII文件和二进制文件。,例:整数10000在内存中的存储形式以及分别按ASCII码形式和二进制形式输出如下图所示:,