1 / 49

第十章 文件

第十章 文件. 教 材 : C 程序设计导论. 主讲:谭成予 nadinetan@163.com. 武汉大学计算机学院. 文件的基本概念. 常用文件操作的标准函数. 文件使用举例. 本讲重点. 文件 的基本概念 文件:存储在外部介质上数据的集合 , 是操作系统数据管理的单位. 使用数据文件的目的 1 、数据文件的改动不引起程序的改动 —— 程序与数据分离 2 、不同程序可以访问同一数据文件中的数据 —— 数据共享 3 、能 长期保存 程序运行的中间数据或结果数据. 文件分类 按文件的逻辑结构: 记录文件:由具有一定结构的记录组成(定长和不定长)

fergal
Télécharger la présentation

第十章 文件

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 第十章 文件 教 材: C程序设计导论 主讲:谭成予 nadinetan@163.com 武汉大学计算机学院

  2. 文件的基本概念 常用文件操作的标准函数 文件使用举例 本讲重点

  3. 文件的基本概念 • 文件:存储在外部介质上数据的集合,是操作系统数据管理的单位 使用数据文件的目的 1、数据文件的改动不引起程序的改动——程序与数据分离 2、不同程序可以访问同一数据文件中的数据——数据共享 3、能长期保存程序运行的中间数据或结果数据

  4. 文件分类 • 按文件的逻辑结构: • 记录文件:由具有一定结构的记录组成(定长和不定长) • 流式文件:由一个个字符(字节)数据顺序组成 • 按存储介质: • 普通文件:存储介质文件(磁盘、磁带等) • 设备文件:非存储介质(键盘、显示器、打印机等) • 按数据的组织形式: • 文本文件: ASCII文件,每个字节存放一个字符的ASCII码 • 二进制文件:数据按其在内存中的存储形式原样存放 文件的基本概念

  5. 如 int型数10000 ASCII形式 0011000100110000001100000011000000110000 0010011100010000 0010011100010000 内存存储形式 二进制形式 文本文件特点: 存储量大、速度慢、便于对字符操作 文件的基本概念 二进制文件特点: 存储量小、速度快、便于存放中间结果

  6. 输入文件缓冲区 磁盘文件 缓冲文件系统: 程序数据区 a 输出文件缓冲区 文件处理方法 • 缓冲文件系统:高级文件系统,系统自动为正在使用的文件开辟内存缓冲区 • 非缓冲文件系统:低级文件系统,由用户在程序中为每个文件设定缓冲区

  7. 程序 指令区 用户数据区 磁盘 缓冲区 非缓冲文件系统: 文件处理方法 • 缓冲文件系统:高级文件系统,系统自动为正在使用的文件开辟内存缓冲区 • 非缓冲文件系统:低级文件系统,由用户在程序中为每个文件设定缓冲区

  8. 文件类型指针 • 文件结构体FILE • 缓冲文件系统为每个正使用的文件在内存开辟文件信息区 • 文件信息用系统定义的名为FILE的结构体描述 • FILE定义在stdio.h中 typedef struct { int _fd; //文件号 int _cleft; //缓冲区中剩下的字符数 int _mode; //文件操作方式 char *_next; //文件当前读写位置 char *_buff; //文件缓冲区位置 }FILE;

  9. 文件类型指针 • 指针变量说明: FILE *fp; • 用法: • 文件打开时,系统自动建立文件结构体,并把指向它的指针返回来,程序通过这个指针获得文件信息,访问文件 • 文件关闭后,它的文件结构体被释放

  10. 文件名 文件使用 方式 操作系统 C程序 文件类型指针 磁盘 文件类型指针 • 指针变量说明: FILE *fp;

  11. 文件的基本概念 常用文件操作的标准函数 文件使用举例 本讲重点

  12. C程序打开文件 操作系统 判断 文件操作失败 C程序打开失败 文件操作成功 C程序对文件进行读写 执行C其它语句 C程序发出关闭命令 操作系统关闭文件 文件的使用流程 文件的操作流程

  13. 文件的打开与关闭 • C文件操作用库函数实现,包含在stdio.h • 文件使用方式:打开文件-->文件读/写-->关闭文件 • 系统自动打开和关闭三个标准文件: • 标准输入------键盘stdin • 标准输出------显示器stdout • 标准出错输出-----显示器stderr • 打开文件fopen • 函数原型:FILE *fopen(char *name,char *mode) 要打开的文件名 使用文件方式 • 功能:按指定方式打开文件 • 返回值:正常打开,为指向文件结构体的指针;打开失败,为NULL

  14. 含义 文件使用方式 “r/rb” (只读) 为输入打开一个文本/二进制文件 “w/wb” (只写) 为输出打开或建立一个文本/二进制文件 “a/ab” (追加) 向文本/二进制文件尾追加数据 “r+/rb+” (读写) 为读/写打开一个文本/二进制文件 “w+/wb+” (读写) 为读/写建立一个文本/二进制文件 “a+/ab+” (读写) 为读/写打开或建立一个文本/二进制文件 文件的打开与关闭

  15. 文件的打开与关闭 例 FILE *fp; fp= fopen (“c:\\fengyi\\bkc\\test.dat”,”r”); 例 FILE *fp; char *filename=“c:\\fengyi\\bkc\\test.dat” fp= fopen(filename,”r”); 例 文件打开与测试 FILE *fp; fp=fopen(“aa.c”,“w”); if(fp==NULL) { printf(“File open error!\n”); exit(0); }

  16. 文件关闭fclose • 作用:使文件指针变量与文件“脱钩”,释放文件结构体和文件指针 • 函数原型:int fclose(FILE *fp) 文件打开时返回的文件类型指针 • 功能:关闭fp指向的文件 • 返值:正常关闭为0;出错时,非0

  17. 缓冲文件系统: 输入文件缓冲区 磁盘文件 程序数据区 a fclose 输出文件缓冲区 文件关闭fclose • 作用:使文件指针变量与文件“脱钩”,释放文件结构体和文件指针 • 函数原型:int fclose(FILE *fp) 不关闭文件可能会丢失数据

  18. 文本文件的读写 • 字符I/O:fputc与fgetc • fputc • 函数原型:int fputc(int c, FILE *fp) • 功能:把一字节代码c写入fp指向的文件中 • 返值:正常,返回c;出错,为EOF • fgetc • 函数原型:int fgetc(FILE *fp) • 功能:从fp指向的文件中读取一字节代码 • 返值:正常,返回读到的代码值;读到文件尾或出错,为EOF

  19. 文本文件的读写 文件I/O与终端I/O #define putc(ch,fp) fputc(ch,fp) #define getc(fp) fgetc(fp) #define putchar( c ) fputc(c,stdout) #define getchar( ) fgetc(stdin)

  20. #include <stdio.h> main() { FILE *fp; char ch,*filename=“out.txt”; if((fp=fopen(filename,"w"))==NULL) { printf("cannot open file\n"); exit(0); } printf("Please input string:"); ch=getchar(); while(ch!='#') { fputc(ch,fp); putchar(ch); ch=getchar(); } fclose(fp); } 例 从键盘输入字符,逐个 存到磁盘文件中,直到 输入‘#“为止

  21. #include <stdio.h> main() { FILE *fp; char ch,*filename=“out.txt”; if((fp=fopen(filename,”r"))==NULL) { printf("cannot open file\n"); exit(0); } while((ch=fgetc(fp))!=EOF) putchar(ch); fclose(fp); } 例 读文本文件内容, 并显示 判断文本文件是否结束

  22. 例 读文本文件内容,并显示 判断二进制文件是否结束 while(!feof(fp)) { c=fgetc(fp); …….. } • feof • 函数原型: int feof(FILE *fp) • 功能:判断文件是否结束 • 返值:文件结束,返回真(非0);文件未结束,返回0

  23. 例 10.3文件拷贝 #include <stdio.h> main() { FILE *in, *out; char ch,infile[10],outfile[10]; scanf("%s",infile); scanf("%s",outfile); if ((in = fopen(infile, "r"))== NULL) { printf("Cannot open infile.\n"); exit(0); } if ((out = fopen(outfile, "w"))== NULL) { printf("Cannot open outfile.\n"); exit(0); } while (!feof(in)) fputc(fgetc(in), out); fclose(in);fclose(out); }

  24. 格式化I/O:fprintf与fscanf • 函数原型: int fprintf(FILE *fp,const char *format[,argument,…]) int fscanf(FILE *fp,const char *format[,address,…]) • 功能:按格式对文件进行I/O操作 • 返值:成功,返回I/O的个数;出错或文件尾,返回EOF 例 从键盘按格式输入数据存到磁盘文件中去 例 fprintf(fp,“%d,%6.2f”,i,t); //将i和t按%d,%6.2f格式输出到fp文件 fscanf(fp,“%d,%f”,&i,&t); //若文件中有3,4.5 ,则将3送入i, 4.5送入t

  25. #include <stdio.h> int main() { char s[80],c[80]; int a,b; FILE *fp; if((fp=fopen("test","w"))==NULL) { puts("can't open file"); exit() ; } fscanf(stdin,"%s%d",s,&a);/*read from keaboard*/ fprintf(fp,"%s %d",s,a);/*write to file*/ fclose(fp); if((fp=fopen("test","r"))==NULL) { puts("can't open file"); exit(); } fscanf(fp,"%s%d",c,&b);/*read from file*/ fprintf(stdout,"%s %d",c,b);/*print to screen*/ fclose(fp); return 0; }

  26. 字符串I/O: fgets与fputs • 函数原型: char *fgets(char *s,int n,FILE *fp) int fputs(char *s,FILE *fp) fputs把s指向的字符串写入fp指向的文件 fgets从fp所指文件读n-1个字符送入s指向的内存区, 并在最后加一个‘\0’ (若读入n-1个字符前遇换行符或文件尾(EOF)即结束)

  27. 字符串I/O: fgets与fputs • 功能:从fp指向的文件读/写一个字符串 • 返值: • fgets正常时返回读取字符串的首地址;出错或文件尾,返回NULL • fputs正常时返回写入的最后一个字符;出错为EOF

  28. #include<stdio.h> int main() { FILE *fp; char string[81]; if((fp=fopen("file.txt","w"))==NULL) { printf("cann't open file");exit(0); } while(strlen(gets(string))>0) {fputs(string,fp); fputs("\n",fp); } fclose(fp); if((fp=fopen("file.txt","r"))==NULL) { printf("cann't open file");exit(0); } while(fgets(string,81,fp)!=NULL) fputs(string,stdout); fclose(fp);return 0; } 例 从键盘读入字符串存入文件,再从文件读回显示

  29. 二进制文件读写: 数据块I/O:fread与fwrite • 函数原型: size_t fread(void *buffer,size_t size, size_t count,FILE *fp) size_t fwrite(void *buffer,size_t size, size_t count,FILE *fp) • 功能:读/写数据块 • 返值:成功,返回读/写的块数;出错或文件尾,返回0 • 说明: • typedef unsigned size_t; • buffer: 指向要输入/输出数据块的首地址的指针 • size: 每个要读/写的数据块的大小(字节数) • count: 要读/写的数据块的个数 • fp: 要读/写的文件指针 • fread与fwrite 一般用于二进制文件的输入/输出

  30. 例 float f[2]; FILE *fp; fp=fopen(“aa.dat”,“rb”); fread(f,4,2,fp); for(i=0;i<2;i++) fread(&f[i],4,1,fp); 例 struct student { int num; char name[20]; char sex; int age; float score[3]; }stud[10]; for(i=0;i<10;i++) fread(&stud[i],sizeof(struct student),1,fp);

  31. 从键盘输入4个学生数据,把他们转存到磁盘文件中去 #include <stdio.h> #define SIZE 2 struct student_type { char name[10]; int num; int age; char addr[15]; }stud[SIZE]; int main() { int i; for(i=0;i<SIZE;i++) scanf("%s%d%d%s",stud[i].name,&stud[i].num, &stud[i].age,stud[i].addr); save(); display(); }

  32. 从键盘输入4个学生数据,把他们转存到磁盘文件中去 void save() { FILE *fp; int i; if((fp=fopen("d:\\fengyi\\exe\\stu_dat","wb"))==NULL) { printf("cannot open file\n"); return; } for(i=0;i<SIZE;i++) if(fwrite(&stud[i],sizeof(struct student_type),1,fp)!=1) printf("file write error\n"); fclose(fp); }

  33. 从键盘输入4个学生数据,把他们转存到磁盘文件中去 void display() { FILE *fp; int i; if((fp=fopen("d:\\fengyi\\exe\\stu_dat","rb"))==NULL) { printf("cannot open file\n"); return; } for(i=0;i<SIZE;i++) {fread(&stud[i],sizeof(struct student_type),1,fp); printf("%-10s %4d %4d %-15s\n",stud[i].name, stud[i].num,stud[i].age,stud[i].addr); } fclose(fp); }

  34. 文件的定位 • 几个概念 • 文件位置指针-----指向当前读写位置的指针 • 读写方式 • 顺序读写:位置指针按字节位置顺序移动 • 随机读写:位置指针按需要移动到任意位置 • rewind函数 • 函数原型: void rewind(FILE *fp) • 功能:重置文件位置指针到文件开头 • 返值:无

  35. 例 对一个磁盘文件进行显示和复制两次操作 文件的定位 #include <stdio.h> int main() { FILE *fp1,*fp2; fp1=fopen("d:\\fengyi\\bkc\\ch12_4.c","r"); fp2=fopen("d:\\fengyi\\bkc\\ch12_41.c","w"); while(!feof(fp1))putchar(getc(fp1)); rewind(fp1); while(!feof(fp1))putc(getc(fp1),fp2); fclose(fp1); fclose(fp2); return 0; }

  36. fseek函数 • 函数原型: int fseek(FILE *fp,long offset,int whence) • 功能:改变文件位置指针的位置 • 返值:成功,返回0;失败,返回非0值 文件指针 位移量(以起始点为基点,移动的字节数) >0向后移动 <0向前移动 起始点 文件开始SEEK_SET 0 文件当前位置SEEK_CUR 1 文件末尾SEEK_END 2 例 fseek(fp,100L,0); fseek(fp,50L,1); fseek(fp,-10L,2);

  37. ftell函数 • 函数原型: long ftell(FILE *fp) • 功能:返回位置指针当前位置(用相对文件开头的位移量表示) • 返值:成功,返回当前位置指针位置;失败,返回-1L, 例 磁盘文件上有3个学生数据,要求读入第1,3学生数据并显示 例 求文件长度(ch12_101.c)

  38. int main() { int i; FILE *fp; if((fp=fopen("studat","rb"))==NULL) { printf("can't open file\n");exit(0); } for(i=0;i<3;i+=2) { fseek(fp,i*sizeof(struct student_type),0); fread(&stud[i],sizeof(struct student_type),1,fp); printf("%s %d %d %s\n", stud[i].name,stud[i].num,stud[i].age,stud[i].addr); } fclose(fp); return 0; } #include <stdio.h> struct student_type { int num; char name[10]; int age; char addr[15]; }stud[3];

  39. #include <stdio.h> int main() { FILE *fp; char filename[80]; long length; gets(filename); fp=fopen(filename,"rb"); if(fp==NULL) printf("file not found!\n"); else {fseek(fp,0L,SEEK_END); length=ftell(fp); printf("Length of File is %1d bytes\n",length); fclose(fp); } return 0; }

  40. 出错的检测 • ferror函数 • 函数原型: int ferror(FILE *fp) • 功能:测试文件是否出现错误 • 返值:未出错,0;出错,非0 • 说明 • 每次调用文件输入输出函数,均产生一个新的ferror函数值,所以应及时测试 • fopen打开文件时,ferror函数初值自动置为0

  41. clearerr函数 • 函数原型: void clearerr(FILE *fp) • 功能:使文件错误标志置为0 • 返值:无 • 说明:出错后,错误标志一直保留,直到对同一文件调clearerr(fp)或rewind或任何其它一个输入输出函数

  42. 例 ferror()与clearerr()举例 #include <stdio.h> int main(void) { FILE *stream; stream =fopen("DUMMY.FIL", "w"); getc(stream); if (ferror(stream)) { printf("Error reading from DUMMY.FIL\n"); clearerr(stream); } if(!ferror(stream)) printf("Error indicator cleared!"); fclose(stream); return 0; }

  43. 文件的基本概念 常用文件操作的标准函数 文件使用举例 本讲重点

  44. /*L10-5.C: 输入一个文件名,读出该文件内容并反向显示出来。*/ #include <stdio.h> int main(void) { FILE *fp; char filename[20]; printf(“please input filename:”); scanf(“%s”,filename); if((fp=fopen(filename,”rb”))==NULL) { printf(“Error opening file %s\n”,filename); exit(1); } fseek(fp,1L,2);/*设置文件指针位于文件结束标记的前一个位置*/ while(fseek(fp,-2L,1)) /*文件指针退回一个位置*/ putchar(fgetc(fp)); return 0; }

  45. 例10.6 编程实现在给定的文件中找到指定位置的字符,并显示出来。文件名和字符位置都在命令行中给出。 分析:假定在操作系统提示符下面输入的命令行内容为: show exam.c 139 算法描述如下: if(命令行参数个数!=3) 显示出错信息,并终止程序的执行; 按照只读模式打开给定文件名; if(打开文件失败) 显示打开忘记失败,同时终止程序执行; 取得要求显示的字符的位置编号; 定位文件指针到指定位置; if(定位失败) 显示定位失败,同时终止程序执行; 读取指定位置字符,并显示出来;

  46. long int atol(const char *str); 功能是将str指向的字符转换成长整型的值,该函数要求str指向的字符串必须含有合法的整型数据,否则返回0。 #include <stdio.h> #include <stdlib.h> int main(int argc,char *argv[]) { FILE *fp; if(argc!=3) { printf(“命令格式错误\n”); exit(1); } if((fp=fopen(argv[1],”rb”))==NULL) { printf(“打开文件失败\n”); exit(1); } if(fseek(fp,atol(argv[2]),0) { printf(“文件定位出错\n”); exit(1); } printf(“在%ld位置的字符是%c\n”,atol(argv[2]),fgetc(fp)); fclose(fp); return 0; }

  47. 例10.7 编程实现UNIX中的cat命令的功能,该命令使用格式如下: cat [filename1 [filename2] [……]] 该命令功能为显示指定的文件内容,如果cat命令后面没有指定任何文件 名,则从键盘读入信息显示在标准终端上,如果指定多个文件名,则依次 显示各文件内容。 分析: if(命令行参数个数==1) filecopy(stdin,stdout); else while(还有文件没有处理完) { 取下一个要显示的文件名,按只读模式打开打开该文件; if(打开失败) 显示打开文件失败信息,终止程序执行; else { filecopy(指定文件,stdout); 关闭已打开文件; } }

  48. /*filecopy:copy file ifp to file ofp*/ void filecopy(FILE *ifp,FILE *ofp) { int c; while((c=getc(ifp))!=EOF) putc(c,ofp); } #include <stdio.h> int main(int argc,char *argv[]) { FILE *fp; void filecopy(FILE *,FILE *); if(argc==1) filecopy(stdin,stdout); else while(--argc>0) if((fp=fopen(*++argv,”r”))==NULL) { printf(“cat:can’t open %s\n”,*argv); return1 ; } else { filecopy(fp,stdout); fclose(fp); } return 0; }

  49. THE END

More Related