240 likes | 382 Views
第12单元 文件. 学习要求. 掌握文件概念 熟练掌握文件类型指针 熟练掌握文件的打开、关闭 熟练掌握文件的读写. C 文件概述. 文件是存储在外存上的数据的集合。 操作系统是以文件为单位进行数据管理的。 操作系统将输入输出设备看作是文件(设备文件)。例如, scanf 是从终端键盘输入数据,终端键盘就是输入文件; printf 是向显示器或打印机输出数据,显示器或打印机就是输出文件。 程序运行时也可以从磁盘文件中输入数据,或向磁盘文件输出数据。. C 文件概述. C 语言把文件看成一个一个字符(字节)的序列,由一个一个字符(字节)的数据组成。
E N D
学习要求 • 掌握文件概念 • 熟练掌握文件类型指针 • 熟练掌握文件的打开、关闭 • 熟练掌握文件的读写
C文件概述 • 文件是存储在外存上的数据的集合。 • 操作系统是以文件为单位进行数据管理的。 • 操作系统将输入输出设备看作是文件(设备文件)。例如,scanf是从终端键盘输入数据,终端键盘就是输入文件; printf是向显示器或打印机输出数据,显示器或打印机就是输出文件。 • 程序运行时也可以从磁盘文件中输入数据,或向磁盘文件输出数据。
C文件概述 • C语言把文件看成一个一个字符(字节)的序列,由一个一个字符(字节)的数据组成。 • 根据数据的组织形式,C数据文件分为ASCII文件和二进制文件。 • ASCII文件又称为文本文件,每个字节放一个ASCII码,代表一个字符。 • 二进制文件是把数据按内存中的存储格式进行存放。 • 例:整数10000 • ASCII文件占5个字节,分别存放31H,30H,30H,30H,30H • 二进制文件占4个字节,分别是00H,00H,27H,10H
输出 输出 输出文件 缓冲区 外存 程序 数据区 输入 输入文件 缓冲区 输入 C文件概述 • C数据文件是“流式文件”,是一个字节流或二进制流。 • C语言中对文件的读写是以字节为单位的。输入输出的数据流的开始和结束仅受程序控制而不受物理符号(如回车符)控制。 • 缓冲文件系统:系统自动在内存为每一个正在读写的文件开辟一个缓冲区。文件的读写都经过缓冲区。 内存
文件类型指针 • 缓冲文件系统中,每个正在使用的文件都在内存中开辟一个区,用来存放文件的信息。包括文件名、文件状态、文件当前位置等。 • 文件信息保存在由系统定义的结构体变量FILE中。 typedef struct{ short level; //缓冲区满或空的程度 unsigned flags; //文件状态标志 char fd; //文件描述符 unsigned char hold; //如无缓冲区不读取字符 short bsize; //缓冲区大小 unsigned char *buffer; //数据缓冲区的位置 unsigned char *curp; //指针,当前的指向 unsigned istemp; //临时文件,指示器 short token; //用于有效性检查 }FILE;
文件类型指针 • 可以定义FILE类型变量,存放文件信息 • FILE f; • 定义指向FILE类型的指针,通过文件指针访问文件。 • FILE *fp;
文件的打开和关闭 • 对文件进行访问,必须先打开文件;访问结束后应当关闭文件。 • 打开文件: • FILE *文件指针; • 文件指针=fopen(文件名,打开方式); • 关闭文件: • fclose(文件指针);
文件打开关闭举例 • 要想从a1.dat输入数据: FILE *fp; fp=fopen("a1.dat","r"); …… fclose(fp); a1.dat: 82,34,55 通知编译系统打开文件的方式。以“r”方式打开的文件必须存在。 通知编译系统要打开的文件名;当路径与C源文件一致时,可以只写文件名。 fp指向a1.dat
文件的读:fscanf函数 • 格式: • fscanf(文件指针,格式字符串,输入表列); • 例: • fscanf(fp,"%d,%d,%d",&a,&b,&c); • 编写程序,找出a1.dat文件三个数据中最小 a1.dat: 82,34,55 aa.txt: 82 34 55 • 思考:文件为aa.txt,如何读取数据? • 思考:如果不知道有几个数据怎么办,如何读取数据? • 函数feof(fp):检查文件是否结束。遇文件结束返回非0,否则返回0。
文件的写:fprintf函数 • 格式: • fprintf(文件指针,格式字符串,输出表列); • 例: • FILE *fp; • fp=fopen("a2.dat","w"); • fprintf(fp,"%d\n",x); • 编写程序,将100-200之间的素数找出来并保存在a2.dat文件中。 a2.dat: 101 103 107 109 113 121 127 131 137 ……
fscanf和fprintf小结 • fscanf和fprintf函数很直观,大家可以对照scanf和printf函数掌握。多了一个文件指针参数。 • “r”方式打开文件,用fscanf输入数据。 • “w”或“a”方式打开文件,用fprintf输出数据。“w”方式每次运行都重新写数据,“a”方式每次运行都追加写数据。 • 在输入时将文本文件的ASCII码数据转为二进制形式;在输出时将二进制形式数据转为字符。运行效率低。建议分别用fread函数和fwrite函数。 实验指导
*其他文件读写函数 • fgetc函数和fputc函数 • 对照getchar()和putchar(ch) • 每次读写一个字符 • fread和fwrtie函数 • 用来读写数据项 • getw函数和putw函数 • 读写一个字(int型) • fgets函数和fputs函数 • 对照gets()和puts(ch) • 每次读写一个字符串
*fputc和fgetc 实验指导 • 格式: • fgetc(fp) • fputc(ch,fp) • 例:将键盘上输入的一些字符送到磁盘上,直到输入“#”为止。 • 例:文件复制。 • 函数feof(fp):检查文件是否结束。遇文件结束返回非0,否则返回0。 • 改为“rb”和“wb”方式(二进制文件读写),复制更具通用性,可以复制图片、word文档等。
*fread和fwrtie函数 • fread和fwrtie函数用来读写一个数据块。 • 一般形式: • fread(buffer,size,count,fp); • fwrite(buffer,size,count,fp); • 说明: • buffer是指针。对fread来说是读入数据的存放地址;对fwrite来说是输出数据的地址。 • size是要读写的字节数(一个数据块) • count是读写的数据块个数 • fp读写的文件指针 • 如果文件以二进制形式打开,用fread和fwrtie函数可以读写任何信息
*理解fwrite和fread函数 # include<stdio.h> void main(){ double num=1.0/3; FILE *p1,*p2; p1=fopen("x1.txt","w"); p2=fopen("x2.txt","w"); fprintf(p1,"%.2f",num); fwrite(&num,sizeof(double),1,p2); fclose(p1); fclose(p2); } 最精确和一致的存储数字的方法是使用与程序中相同的位格式。双精度的num应该存储在double大小的单元中。fwrite将数据存储在一个与程序具有相同表示方法的文件中。没有从数字到文本的转换,不损失精度。 双精度的num根据输出格式可以保存为不同字节的字符串。读取文件时,数据精度无法恢复。 用fwrite函数写的数据相应用fread函数读取
*fread和fwrtie函数 • 例:将数组写入文件 int a[10]={1,2,3,4,5,6,7,8,9,10},*p=a; FILE *f; f=fopen("test.dat","w"); for(p=a;p<a+10;p++) fwrite(p,sizeof(int),1,f); fclose(f); • 例:读出文件中的数据 int a[10],*p=a,i; FILE *f; f=fopen("test.dat","r"); for(p=a;p<a+10;p++) fread(p,sizeof(int),1,f); fclose(f); for(i=0;i<10;i++) printf("%d\n",a[i]); 实验指导
文件小结 • C程序将输入看作字节流,流的来源可以是文件、输入设备(如键盘)等。同样C程序将输出也看作字节流,流的目的地可以是文件、输出设备(如显示器)等。 • 要存取文件,需要创建一个文件指针。类型为FILE *并将其与一个具体的文件名关联起来。后续的代码就可以使用这个指针而不是文件名来处理该文件。
文件小结 • C如何解释输入和输出的字节流,取决于所使用的输入输出函数。程序可以不加改动地读取或存储字节,也可以将字节解释为字符。如果要在不损失精度的前提下保存或恢复数字数据,利用二进制模式,使用fread和fwrite函数。如果不保存文本信息或是要创建可以用普通文本编辑器查看的文件,使用文本模式和诸如fprintf、fputc之类的函数。 • 通常读取一个文件的程序使用循环读取输入,直到遇到文件的结尾。文件结尾判断的函数是feof
实验指导 • 编写一个统计身高的程序。请求出文件“list.txt”(下载)中记录的所有人的平均身高及最高的人,并把结果输出到屏幕上。 FILE *f; char name[40]; int highest; f=fopen("list.txt","r"); while(!feof(f)){ fscanf(f,"%s",name); fscanf(f,"%d",&highest); …… }
实验指导 • 编写一个名为c15_2.c的程序,其功能为,读入文本文件test1.txt的内容,将所有英文字母及换行符保存到新的文本文件test2.txt中。 • 提示:(可以参考课件“文件复制”) • 新建一个文本文件test1.txt,内容自己定。 • 用只读方式打开文本文件test1.txt,用只写(或读写)方式打开文本文件test2.txt。 • 用fgetc函数读入一个字符,判断是否字母或换行符,再用fputc函数将一个字符写入到磁盘文件。 • if(c>=65 && c<=90 ||c>=97 && c<=122 || c==10 || c==13) fputc(c,fout);
实验指导 • 编写一个名为c15_3.c的程序,实现如下功能:有5个学生,每个学生有平时成绩、期末考试成绩和总评成绩(总评成绩=平时成绩*30%+期末考试成绩*70%),从键盘输入学生数据(包括学号、姓名、平时成绩和期末考试成绩),计算出总评成绩,将原有数据和计算出的总评成绩存放在磁盘文件“stud.dat”中。 • 提示: • 可先定义一个用于存放学生数据的结构体类型: struct student { char num[6]; char name[8]; int score[3]; }stu[5];
实验指导 • 键盘输入5个学生的数据: for(i=0;i<5;i++) scanf(“%s%s%d%d”,stu[i].num,stu[i].name,&stu[i].score[0],&stu[i].score[1]); 在输入时,数据间用空格隔开 • 计算总评成绩 • 建立文件指针f,指向“stud.dat”,“wb”方式 • 用fwrite函数将数据写入二进制文件。 for(i=0;i<5;i++) fwrite(&stu[i],sizeof(struct student),1,f); (可以比较与用fprintf函数建立的文件有什么不同) • 可参考书本例13.3。