780 likes | 972 Views
第十章 文件. 本章学习重点: 文件的基本概念 文件的打开、关闭 文件的读写 文件的定位、文件的检测. 本章目录. 第二十五讲 文件概述、文件打开与关闭 第二十六讲 文件读写 第二十七讲 文件的定位和文件的检测 本章小结. 结束. 第二十五讲 文件概述、文件打开与关闭. 【思考题 10-1 】 如果我们需要将程序运行结果存放到外存时,应该用什么方法存储呢?应该怎样读入数据或存储数据呢? ( 一 ) 程序分析 我们如果要将一个字符串 "This is a C program." 存放到一个文件中,应该怎么设计程序呢?请看下例。. 返回到本章目录.
E N D
第十章 文件 本章学习重点: 文件的基本概念 文件的打开、关闭 文件的读写 文件的定位、文件的检测
本章目录 第二十五讲 文件概述、文件打开与关闭 第二十六讲 文件读写 第二十七讲 文件的定位和文件的检测 本章小结 结束
第二十五讲文件概述、文件打开与关闭 【思考题10-1】如果我们需要将程序运行结果存放到外存时,应该用什么方法存储呢?应该怎样读入数据或存储数据呢? (一)程序分析 我们如果要将一个字符串"This is a C program."存放到一个文件中,应该怎么设计程序呢?请看下例。 返回到本章目录
(二)编写程序代码 #include <stdio.h> main() { FILE *fp; fp=fopen("file1.txt","w"); fprintf(fp,"This is a C program."); fclose(fp); } 返回到本章目录
(三)调试运行程序 在这个程序中,建立了一个名为"file1.txt"的文件,并将字符串"This is a C program."通过fprintf函数输出到文件中保存起来。同理,也可以用fscanf函数从文件"file1.txt"中输入该内容。该程序在屏幕上没有输出信息。 返回到本章目录
1.文件的定义 所谓文件,是指存储在外部介质上的数据的集合。计算机把所有外部设备都当做文件来对待,这样的文件称为设备文件。例如,键盘是输入文件,显示屏和打印机是输出文件,我们可以用scanf函数输入键盘文件,printf函数输出显示屏和打印机文件。实际上,外部设备的输入/输出操作就是读/写设备文件的过程,对设备文件的读/写与对一般磁盘文件的读/写方法完全相同。 返回到本章目录
2.数据文件的存储形式 根据数据的组织形式,可分为字符文件和二进制文件。 1)字符文件(文本文件) 字符文件又称文本(text)文件,它的每一个字节放一个ASCII代码,代表一个字符(即一个字符占一字节)。 2)二进制文件 二进制是把内存中的数据按其在内存中的存储形式原样输出到磁盘上存放,这类文件可以节省内存空间。 返回到本章目录
3.标准文件系统和非标准文件系统 在过去使用的C版本中(如UNIX系统下使用的C)有两种对文件的处理方法:一种叫“缓冲文件系统”,一种叫“非缓冲文件系统”。 1)缓冲文件系统 所谓缓冲文件系统,是指系统自动地在内存区为每一个正在使用的文件名开辟一个缓冲区。从内存向磁盘输出数据必须先送到内存中的缓冲区,装满缓冲区后才一起送到磁盘去。 返回到本章目录
2)非缓冲文件系统 所谓“非缓冲文件系统”是指系统不自动开辟确定大小的缓冲区,而由程序为每个文件设定缓冲区。在UNIX系统下,用缓冲文件系统来处理文本文件,用非缓冲文件系统来处理二进制文件。 返回到本章目录
4.文件类型指针 1)文件类型FILE的定义 在进行文件操作时,要用到文件指针。文件指针用来指向被操作文件的有关信息(如文件名、文件状态及文件当前位置等)。这些信息是保存在一个结构体变量中的。该结构体类型是由系统定义的,类型名为FILE。有了FILE类型以后可以定义文件类型的指针变量。 返回到本章目录
2)文件类型指针的定义 (1)文件类型指针的定义格式如下: (2)功能。定义一个文件类型的指针,使用这个指针可以对文件进行各种操作。 3)标准文件操作的四个基本步骤 (1)文件类型指针的定义; (2)打开标准文件; (3)标准文件的读或写的操作; (4)标准文件的关闭操作。 FILE *指针变量标识符; 返回到本章目录
在对文件操作之前必须“打开”文件,打开文件的作用实际上是建立该文件的信息结构体,并且给出指向该信息结构体的指针以便对该文件进行访问。文件使用结束之后应该“关闭”该文件。文件的打开与关闭是通过调用fopen和fclose函数来实现的。在对文件操作之前必须“打开”文件,打开文件的作用实际上是建立该文件的信息结构体,并且给出指向该信息结构体的指针以便对该文件进行访问。文件使用结束之后应该“关闭”该文件。文件的打开与关闭是通过调用fopen和fclose函数来实现的。 返回到本章目录
5.文件的打开(fopen函数) • ANSI C规定了标准输入/输出函数库,用fopen()函数来实现文件的打开,其调用的一般格式如下: • 其中,fname是要打开的文件名,可以是字符串常数、字符型数组或字符型指针,文件名也可以带路径。mode表示文件的使用方式,它规定了打开文件的目的,如表10-1所示。 FILE *fp; fp=fopen(fname,mode) ; 返回到本章目录
表10-1 fopen函数中的文件使用方式 返回到本章目录
如果文件名中包括文件的路径,则用双反斜线表示路径(双反斜线“\\”中的第一个表示转义字符,第二个表示路径分隔符“\”)。例如: 如果文件名中包括文件的路径,则用双反斜线表示路径(双反斜线“\\”中的第一个表示转义字符,第二个表示路径分隔符“\”)。例如: FILE *fp; fp=fopen("c:\\user\\abc.txt","w"); 其意义是以只写方式打开C驱动器磁盘下文件夹user 中的文件abc.txt,并使文件指针fp指向该文件。 返回到本章目录
6.文件的关闭(fclose 函数) 文件使用完后应将它关闭,以保证本次文件操作的有效。用fclose函数关闭文件,其一般形式为: 例如: fclose(fp); 如果文件关闭成功,fclose函数返回值为0,否则返回EOF(-1)。这可以用ferror函数来测试。 fclose(文件指针); 返回到本章目录
练一练 【练习10-1】以只读的方式打开D盘的"d:\abc.txt"文件,语句应该怎么写? 解:打开文件函数为fopen,第一个参数为文件名;第二个为打开文件的方式,只读方式的模式为"r",所以语句写为: FILE *fp; fp=fopen("d:\\abc.txt","r"); 返回到本章目录
【练习10-2】以读写的方式打开D盘的"d:\abc.txt"文件,语句应该怎么写?(注意假设D盘中有该文件和没有该文件的两种情况。)【练习10-2】以读写的方式打开D盘的"d:\abc.txt"文件,语句应该怎么写?(注意假设D盘中有该文件和没有该文件的两种情况。) 解:打开文件函数为fopen,第一个参数为文件名,文件名注意两侧有双括号引上,并将单个的斜线“\”改为双斜线“\\”即可。第二个为打开文件的方式,读写方式的方式为"r+"或"w+"。使用"r+"的情况是在不删除原有文件时(没有该文件时会出错);而"w+"则会删除原有文件,然后新建一个该名的文件。所以语句写为: FILE *fp; fp=fopen("d:\\abc.txt ","r+"); /*不删除原有文件时*/ 或: fp=fopen("d:\\abc.txt ","w+"); /*删除后新建该文件*/ 返回到本章目录
【练习10-3】 在【练习10-1】中打开"d:\abc.txt"文件后,如果想关闭该文件的语句是什么? 解:关闭文件的函数为fclose,参数为要关闭的文件指针名。所以语句写为: fclose(fp); 返回到本章目录
第二十六讲文件读写 一、fputc函数和fgetc函数 二、fputs函数和fgets函数 三、fwrite函数和fread函数 四、fprintf函数和fscanf函数 练一练 返回到本章目录
一、fputc函数和fgetc函数 【思考题10-2】若想将一些字符写入一个文本文件,然后输出到屏幕上,应该如何读写程序? (一)程序分析 设计一个程序,将字符A、B、C和EOF写入文件"c:\file1.txt"中,然后再从文件"c:\file1.txt"中读出所有的字符并显示在屏幕上。 返回到本章目录
(二)编写程序代码 #include "stdio.h" main() { char a='A',b='B',c='C',filename[20]; FILE *fp; clrscr(); /*清屏*/ printf("\nPlease input the write filename:"); scanf("%s",filename); /*从键盘读入文件名*/ if((fp=fopen(filename,"w"))==NULL) /*以只写方式打开文件*/ { printf("write cannot open file\n"); exit(0); } fputc(a,fp); /*将字符变量a的值存入文件*/ 返回到本章目录
(三)调试运行程序 程序运行时,用户先输入文件路径及文件名"c:\file1.txt",程序以"w"方式打开文件,然后由函数fputc()依次将保存在变量a、b、c中的字符写到文件中,最后写入EOF并关闭文件。通过Windows资源管理器可以看到文件file1.txt被建立,其长度为4字节。然后程序再循环从该文件中输出A、B、C三个字符并显示到屏幕上,当遇到文件结束标志时循环结束。 程序运行结果如下:
1.fputc函数 fputc函数是把一个字符输出(写入)到磁盘文件上,与其完全等价的还有putc()。它们的一般调用形式 和 其中,ch是要输出的字符,它可以是一个字符常量,也可以是一个字符变量。fp是文件指针变量。fputc(ch,fp)函数的作用是将字符(ch的值)输出到fp所指向的文件上。如果输出成功,函数的返回值是输出的字符;如果输出失败,则返回文件结束标志EOF。EOF是在stdio.h中定义的符号常量,值为-1,十六进制表示为0xFF。 fputc(ch,fp); putc(ch,fp); 返回到本章目录
2.fgetc函数 fgetc函数是用来从指定文件中读取一个字符,与它完全等价的还有getc()。它们的调用格式如下: 和 其中,fp为文件指针。该函数的功能是从指定的文件读取一个字符,并赋给字符型变量ch。如果读取成功,函数返回读取的字符;如果遇到文件结束符,则返回一个文件结束标志EOF。 ch=fgetc(fp); ch=getc(fp); 返回到本章目录
二、fputs函数和fgets函数 【思考题10-3】若想将多个字符串写入一个文本文件,然后输出到屏幕上,应该如何读写程序? (一)程序分析 设计一个程序,将字符串"Hello,"、"all "、"the "、"world "、"people!"写入文件"c:\file2.txt"中,然后再从文件"c:\file2.txt"中读出所有的字符串并显示在屏幕上。 返回到本章目录
(二)编写程序代码 #include "stdio.h" main() { char a[][9]={"Hello,","all ","the ","world ","people!"}; char filename[20],out[9]; int i; FILE *fp; clrscr(); /*清屏*/ printf("\nPlease input the write filename:"); scanf("%s",filename); /*从键盘读入文件名*/ if((fp=fopen(filename,"w"))==NULL) /*以只写方式打开文件*/ { printf("write cannot open file\n"); exit(0); } 返回到本章目录
for(i=0;i<=4;i++) fputs(a[i],fp); /*将字符串存入文件*/ fclose(fp); /*以下为从文件中读出各字符串并显示在屏幕上*/ if((fp=fopen(filename,"r"))==NULL) /*以只读方式打开该文件*/ { printf("read cannot open file\n"); exit(0); } while((fgets(out,9,fp))!=NULL) /*当fp指针没到文件尾部,取出一字符串*/ printf("%s",out); fclose(fp); /*关闭该文件*/ } 返回到本章目录
fputc(b,fp); /*将字符变量b的值存入文件*/ fputc(c,fp); /*将字符变量c的值存入文件*/ fputc(0xff,fp); /*将文件结束标志EOF存入文件*/ fclose(fp); /*关闭该文件*/ /*以下为输出文件内容*/ if((fp=fopen(filename,"r"))==NULL) /*以只读方式打开该文件*/ { printf("read cannot open file\n"); exit(0); } while((a=fgetc(fp))!=EOF) /*当文件指针没到文件尾部时*/ putchar(a); fclose(fp); /*关闭该文件*/ } 返回到本章目录
(三)调试运行程序 程序运行时,用户先输入文件路径及文件名"c:\file2.txt",程序以"w"方式打开文件"c:\file2.txt",然后由fputs()依次将字符数组a中的各字符串写到文件"c:\file2.txt"中。然后程序再用循环方式从该文件中读出各字符串并显示到屏幕上。 程序运行结果如下: 返回到本章目录
3.写文件字符串函数fputs() (1)函数调用格式如下: 其中,字符串可以是一个字符串常量,或字符数组名,或字符指针变量名。 (2)功能。向指定文件输出一个字符串,同时将读写位置指针向前移动strlength(字符串长度)字节。如果输出成功,则函数返回值为0;否则,为非0值。 fputs(字符串,文件指针); 返回到本章目录
4.读文件字符串函数fgets() (1)函数调用格式如下: (2)功能。从指定文件中读入一个字符串,存入字符数组/指针中,并在尾端自动加一个结束标志'\0';同时,将读写位置指针向前移动strlength(字符串长度+1)字节。如果在读入规定长度之前遇到文件尾EOF或换行符,读入即结束。 fgets(字符数组名/指针名,字符串长度+1,文件指针); 返回到本章目录
三、fwrite函数和fread函数 【思考题10-4】若想向文件中输入或从文件中读出结构体类型(成员为多种数据类型)的信息,应该用什么样的方法比较好? (一)程序分析 设计一个程序,从键盘输入一批学生数据,然后存储到磁盘文件上,再输出磁盘文件中的学生数据到屏幕上。注意成块输入fread函数和成块输出fwrite函数的使用方法。 返回到本章目录
(二)编写程序代码 #include "stdio.h" #include "string.h" struct student /*定义学生结构体类型*/ { int num; /*定义学号*/ char name[20]; /*定义姓名*/ int chinese,math,english; /*定义语文,数学,英语成绩*/ }; main() { FILE *fp; int i; char ch,filename[30]; float f; struct student stu[30],st; /*定义结构体类型的变量*/ clrscr(); /*清屏*/ printf("\nPlease input the write filename:"); 返回到本章目录
scanf("%s",filename); /*从键盘读入文件名*/ if((fp=fopen(filename,"wb"))==NULL) /*以只写方式打开文件*/ { printf("Cannot open %s file\n",filename); exit(0); } /*循环读入一批学生信息,当输入n或N时输入结束输入*/ i=0; do { printf("please input information of the %d student:",i+1); printf("\nnumber name chinese math english\n"); scanf("%d%s%d%d%d",&stu[i].num,stu[i].name,&stu[i].chinese, &stu[i].math,&stu[i].english); fwrite(&stu[i],sizeof(stu[i]),1,fp); i++; 返回到本章目录
printf("Have another student record(y/n)?"); getchar(); ch=getchar(); }while(ch=='y'||ch=='Y'); /*当输入y或Y时继续输入*/ fclose(fp); /*以下功能为将学生成绩读出并显示到屏幕上*/ if((fp=fopen(filename,"rb"))==NULL) /*以只读方式打开该文件*/ { printf("read cannot open file %s!\n",filename); exit(0); } printf("\nInformation of the student score:"); printf("\n number name chinese math english"); while(fread(&st,sizeof(st),1,fp)==1) 返回到本章目录
printf("\n%5d%7s%5d%5d%5d",st.num,st.name,st.chinese,st.math, st.english); if(!feof(fp)) printf("\n file read error"); fclose(fp); } (三)调试运行程序 首先输入文件名"c:\file3.txt",程序以"wb"方式打开文件"c:\file3.txt",然后输入第一个学生信息,由函数fwrite()依次将一个学生信息写到文件"c:\file3.txt"中,然后出现提示是否继续输入下一条学生信息,当输入y或Y时继续输入,当输入n或N时输入结束输入,关闭该文件。然后以只读方式"rb"打开该文件,程序再用循环方式用函数fread()从该文件中读出各学生信息并显示到屏幕上。 返回到本章目录
程序运行结果如下: 返回到本章目录
5.fwrite函数 (1)fwrite函数调用格式如下: (2)说明。fwrite函数用来向指定文件中写入数据块。其中,buf为被写入数据在内存中存放的起始地址,可以是数组名或指向数组的指针;size为每次要写入的字节数;count为要写入的次数;fp为文件指针。 fwrite(buf,size,count,fp); 返回到本章目录
(3)功能。该函数的功能是从buf所指向的内存区域取出count个数据项写入fp指向的文件中,每个数据项的长度为size,也就是写入的数据块大小为size*count个字节。如果函数执行成功,返回值为实际写入数据项的个数,否则若返回值小于实际需要写入数据项的个数count,则出错。当文件按二进制形式打开时,fwrite函数可以写入任何类型的信息。(3)功能。该函数的功能是从buf所指向的内存区域取出count个数据项写入fp指向的文件中,每个数据项的长度为size,也就是写入的数据块大小为size*count个字节。如果函数执行成功,返回值为实际写入数据项的个数,否则若返回值小于实际需要写入数据项的个数count,则出错。当文件按二进制形式打开时,fwrite函数可以写入任何类型的信息。 返回到本章目录
6.fread函数 (1)fread函数调用格式如下: (2)功能。该函数用于从文件中读取一个数据块。其中,buf为从文件中读取的数据在内存中存放的起始地址,size为一次读取的字节数,count为要读取的次数,fp为文件指针。该函数的功能是从fp所指的文件中,读取长度为size字节的数据项count次,存放到buf所指的内存单元中,所读取的数据块大小为size*count字节。当文件按二进制形式打开时,fread函数可以读出任何类型的信息。函数执行成功时,返回值为实际读出的数据项个数,否则若返回值小于实际需要读出数据项的个数count,则出错。 fwrite(buf,size,count,fp); 返回到本章目录
四、fprintf函数和fscanf函数 【思考题10-5】 若想将多个不同类型的数据写入一个文本文件,然后输出到屏幕上,应该如何读写程序? (一)程序分析 设计一个程序,从键盘输入一批学生信息,并将学生信息写入到一个二进制文件中,然后存储到磁盘文件上,再输出磁盘文件中的学生信息到屏幕上。注意格式化输入fprintf函数和格式化输出fscanf函数的使用方法。 返回到本章目录
(二)编写程序代码 #include "stdio.h" struct student { char name[10]; int num; int age; char addr[15]; }boy[2],*bp; main() { FILE *fp; char ch,filename[20]; int i; clrscr(); /*清屏*/ printf("\nPlease input the write filename:"); gets(filename); /*读取文件名*/ bp=boy; 返回到本章目录
if((fp=fopen(filename,"wb+"))==NULL) { printf("Cannot open file!"); getch(); exit(1); } printf ("input 2 boy information:"); printf("\nname num age addr:\n"); for(i=0;i<2;i++,bp++) scanf("%s%d%d%s",bp->name,&bp->num,&bp->age,bp->addr); bp=boy; for(i=0;i<2;i++,bp++) /*依次将学生信息存入文件中*/ fprintf(fp,"%s %d %d %s\n",bp->name,bp->num,bp->age,bp->addr); fclose(fp); 返回到本章目录
/*以下功能是将信息显示到屏幕上*/ if((fp=fopen(filename,"r"))==NULL) /*以只读方式开该文件*/ { printf("read cannot open file %s!\n",filename); exit(0); } bp=boy; /*bp指针重新指向结构体数组首地址*/ for(i=0;i<2;i++,bp++) /*将文件中学生信息读取到结构体数组中*/ fscanf(fp,"%s %d %d %s\n",bp->name,&bp->num, &bp->age,bp->addr); printf("name\t number age addr\n"); bp=boy; for(i=0;i<2;i++,bp++) printf("%s\t%5d%10d%12s\n",bp->name,bp->num,bp->age,bp->addr); fclose(fp); } 返回到本章目录
(三)调试运行程序 返回到本章目录
7.fprintf函数 fprintf函数与printf函数作用相仿,都是格式化写入函数,只不过写入对象不是终端而是文件。其调用格式为: 该函数的功能是按格式字符串的格式,将输出表列的值写入文件指针所指向的文本文件中。注意:输出表列为变量名,不是变量的地址,不能在变量前加“&”符号。 fprintf(文件指针,格式字符串,输出表列); 返回到本章目录
8.fscanf函数 • fscanf函数与scanf函数作用相仿,都是格式化读取函数,只不过不是从终端读取而是从文件读取。其调用格式为: • 该函数的功能是从文件指针所指向的文本文件中读取数据,按格式字符串的格式存入输入表列变量所指向的内存中。注意:输入表列为变量的地址,除字符串输入(用字符数组名接收该字符串)不加“&”符号外,其他变量名前必须加“&”符号。 fscanf(文件指针,格式字符串,输入表列); 返回到本章目录
9.文件的其他读写函数 (1)判断文件是否结束函数feof(),函数调用格式如下: 其中,fp是文件指针。函数功能为判断文件指针fp所指文件是否结束,如果遇到文件结束,函数返回值为1,否则函数返回值为0。 (2)文件读/写整数函数,putw和getw。对于大多数C编译系统来说,都提供这两个函数,用来对磁盘读/写一个字(整数)。getw函数的调用格式为: feof(fp); 整型变量名=getw(文件指针名); 返回到本章目录
putw函数的调用格式为: 例如: putw(10,fp); 作用是将整数10写入fp所指的文件,而语句: i=getw(fp); 作用是从文件读一个整数到内存,赋给变量i。 putw(整型常量,文件指针名); 返回到本章目录