C语言:文件存取.pdf
![资源得分’ title=](/images/score_1.gif)
![资源得分’ title=](/images/score_1.gif)
![资源得分’ title=](/images/score_1.gif)
![资源得分’ title=](/images/score_1.gif)
![资源得分’ title=](/images/score_05.gif)
《C语言:文件存取.pdf》由会员分享,可在线阅读,更多相关《C语言:文件存取.pdf(12页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、C语言:文件存取初步在磁盘上数据的存储是以OS文件为单位的。OS文件可分为两大类:文本(Text)文件和二进制(Binary)文件。Text 文件可以在屏幕上或打印机上打印(例如在某个Text Editor中打开),是肉眼可读的;而二进制文件,如果也在Text Editor中打开,你看到的可能一片“乱码”。其实,任何文件在磁盘上,存储的都是二进制代码,以字节为单位,每一字节由 8 个二进制位(0 或 1)组成。因此,C 语言统称它为字节流(Byte Stream)。如果说两者有区别,区别在于,对于ASCII 文本文件,每一个字节中的二进制码恰好代表一个ASCII 字符,而且,因为文本文件一般是
2、用于显示或打印的目的,字节流被分成一系列“行”,每一行以回车符和换行符(r n)结尾;而二进制文件,每个字节的二进制码可能不对应于任何可印刷字符,也没有“行”的概念。在 C语言中,这两种文件都可通过文件I/O 库函数(也称流函数)存取(读写)。为了使用键盘输入、屏幕输出和打印机输出,C 语言(以及 DOS)把这些设备也视为文件,称为设备文件。于是,C程序可以用同样的文件I/O(输入输出)函数存取磁盘文件和设备文件。在 stdio.h文件中列出了所有ANSI C 标准文件 I/O 库函数原型及其用到的数据结构的定义。其中,最重要的数据结构是FILE 结构体:FILE 结构体:typedef st
3、ruct short level;/*fill/empty level of buffer*/unsigned flags;/*File status flags */char fd;/*File descriptor */unsigned char hold;/*Ungetc char if no buffer*/short bsize;/*Buffer size */unsigned char *buffer;/*Data transfer buffer*/unsigned char *curp;/*Current active pointer*/unsigned istemp;/*Tem
4、porary file indicator*/short token;/*Used for validity checking*/FILE;任何文件在读写前必须打开。文件标准I/O 是使用缓冲区的。当用fopen()打开一个文件时,存取该文件用的缓冲区在内存中被fopen()建立,fopen()也同时建立一个与存取该文件有关的FILE 结构体,并返回指向该 FILE 结构体的指针。注意,在这个FILE 结构体中,指针变量buffer正是指向所建缓冲区的指针。FILE 结构体还包含与存取该文件有关的信息,当文件在读写过程中,有些信息也在相应地更新。例如,curp 指针总是指向缓冲区中当前要读写的
5、位置。你无须了解FILE 结构体的每一成员的细节,你一般也用不着直接访问FILE 结构体中的成员变量,你只须知道 fopen()返回的 FILE 指针是与所打开的文件相联系的,或者说得简单些,这个FILE 指针指向的就是所打开的文件(虽然实际指向的是与所打开的文件相联系的FILE 结构体)。随后,当用其他标准I/O 函数读或写文件时,你只是简单地引用FILE 指针,以便告诉C,你要读写的是那一个文件。用来读写已打开文件的标准I/O 函数主要包括:fgetc():读单个字符,fgets():读 n 个字符,fputc():写单个字符,fputs():写一字符串。fscanf():读一字符序列,并
6、按接收变量的类型转换。fprintf():把输出变量的内容转换成字符序列,写到文件上。fread():读 n 个字节,fwrite():写 n 个字节。(常用于读写二进制文件)rewind(),fseek():移动文件当前读写位置,ftell():返回文件当前读写位置还要记住,读写结束后,应当用fclose()关闭所打开的文件,以确保缓冲区的内容被写到文件上。标准(ANSI C)输入输出函数:打开文件:FILE *fopen(const char*path,const char*mode);其中,path 字符串指定要打开的文件名,如“C:Dir1File1.txt”;mode字符串指定对该文
7、件的存取方式,如“r”。mode 字符串可以是以下字符的组合:r(读),w(写),a(追加),+(读和写),t(文本方式),b(二进制方式)如果不指定t 或 b,则默认为 t;如果有 r 或 a,则文件必须已存在;如果w,则当文件存在时,清除原内容后再写,否则创建新文件。a 与 w 不同,它不清除原内容,而是在原内容之后补写。+和 r、w、或 a 连用,容许读和写,是否要求原文件存在或是否创建新文件,取决于r、w或 a。fopen()函数返回 FILE 指针,你用 FILE 指针变量(以下为叙述方便,设为Fp)接收这个返回值,随后在用其他I/O 函数读写该文件时,要引用这个FILE 指针变量
8、Fp。或者粗略地说,Fp 就是这个 fopen()打开的、随后要读写的文件。如果打开不成功,fopen()返回 NULL,NULL在 stdio.h 中被#define为整数 0)。例:FILE*Fp;Fp=fopen(“C:Dir1File1.txt”,“r”);/*为读打开,Text 方式 */Fp=fopen(“C:Dir1File1.txt”,“r+”);/*为读写打开,r 要求文件必须存在,Text 方式 */Fp=fopen(“C:Dir1File1.txt”,“wb+”);/*为读写打开,Binary 方式 */fprintf(Fp,“%d,%d,%d”,i,j,k);/*往打开
9、的 Fp 文件上写 */关于文件当前位置指针:所有 I/O 函数都维护文件读写的当前位置指针。当fopen()打开文件成功时,当前位置指针指向文件的开始处(第一个字节)。随后,你可顺序读或写文件。所有执行读或写功能的函数(见后),在读或写 n 个字节后(n=1),当前位置指针均移动n 个字节,即指针自动移动到下一次要读或写的位置(当然不会超过文件尾)。以下在介绍每个函数时,不再特别说明。你也能调用rewind()、fseek()、fsetpos()等函数重置当前位置指针后再读写(所谓“随机读写”)。请勿将文件读写的当前位置指针与FILE 指针、及 FILE 结构体中的buffer指针相混。读写
10、方式:文本方式与二进制方式任何文件都可以以文本方式或二进制方式打开。两者在读写文件时的区别是:文本方式:当写文件时,如果被写的内存字节是0 x0D(r ),它被照写不变,但若是0 x0A(n )则写两个字节0 x0D 0 x0A(r n )到文件上。反之,当读文件时,凡遇到0 x0D 时即 r 时就跳过不计,自动移到下一字节(直到非r ),而 0 x0A(n )照读不误。这也顺便说明了为什么printf()遇到 n 时不仅在屏幕上换行(n )而且也回车(这是 r 的功能)。二进制方式:与文本方式不同,写时即不转换n ,读时也不滤掉r ,任何字节都原封不动地写入文件或读到内存。虽然任何文件的读写
11、方式都可在fopen()时任意指定,但习惯上,一般用文本方式读写文本文件,即 ASCII.txt文件,而用二进制方式读写其他文件。顺便指出,字节 和字符(ASCII)在文件 I/O 中是一个意思,当说字符时,实际也是指存放该字符的 8-bit字节,或该字符的8-bit编码。只是,当处理文本文件时,人们习惯用“字符”,而处理二进制文件时,习惯用术语“字节”。标准设备文件:任何 TurboC 程序开始运行时,都自动打开了5 个设备文件,这5 个 FILE 指针变量名(系统变量)是:stdin标准输入(键盘)文件stdout标准输出(屏幕)文件stderr标准出错输出(屏幕)文件stdprn标准打印
12、(打印机)文件stdaux标准辅助输入输出(串口)文件于是,为了读或写上述某文件,你只须直接引用相应的FILE 指针变量名(代替Fp)。关闭文件:int fclose(FILE*Fp);本函数关闭已打开的文件Fp,如果关闭成功,本函数返回0,否则返回一个非零值(-1)。关闭 意味着:a)释放该文件打开时建立的I/0缓冲区,如果在缓冲区中尚有未写入文件中的数据,在释放前,先写入文件。B)Fp 文件关闭后不能再读写,Fp 指向的 FILE 结构体所占的内存空间也被释放,Fp 置成 NULL。以下介绍主要的读写函数,并以例说明它们的用法。写一个字符(字节):int fputc(int c,FILE*
13、Fp);该函数把 int变量 c 的低 8 位(也可是 char 变量)写到Fp文件的当前位置。该函数的返回值是c 的值或 EOF,EOF表示写操作不成功。另外,宏 putc(c,fp)也能用来写字符c,而#define putchar(c)putc(c),stdout)注意,函数fputc(c,Fp)或 putc(c,Fp)只是写单个字符或字节到文件的当前位置,写完后当前位置自动移动到文件的下一字节位置。于是,你可连续地用这个函数把一串字节顺序写到文件上。读一个字符(字节):int fgetc(FILE*Fp);该函数返回Fp文件当前位置上的那个字节(作为 int类型返回值的低8 位)。如果
14、当前位置是EOF (文件尾),则返回 EOF(stdio.h中定义 EOF为 1)。如果用此函数顺序读ASCII 文件,你可判断返回值是不是EOF而知文件是否读完(ASCII 字符的编码是 0-127,不可能是-1)。但若读非 ASCII 文件,值-1 可能是文件的正文内容,并不一定意味着文件尾。因此,你不能用上述方法判断文件是否读完。但在任何情形,你都能用FILE 结构体中的flags值的第 6 位(从右数)是否为1 知道当前位置是否在文件尾。等价地,你也可以用宏feof(Fp)来判断:feof(Fp)=1意味着 Fp 文件当前在文件尾。此外,文件读写时也可能出错,你可用flags值的第 5
15、 位或 ferror(Fp)宏判断。即在任何I/O 操作之后,若 ferror(Fp)为 1(真),则表示出错。顺便指出,宏getc(Fp)同效于 fgetc(Fp),但 getc(Fp)的值是char型的,而 getchar()定义为:#define getchar()getc(stdin)类似于 fgetc(c,Fp)写的是单个字符,本函数也只是从文件上读单个字符(或字节),如果想读完整个文件,你必须在打开文件后连续地使用本函数,直至文件尾。因为每读一个字符后,文件的当前位置指针自动加1,下一次再读时读的肯定是下一字符,所以你不必自己去移动当前位置指针。例文件:Students.txt 姓
16、名系别性 身高出生入学0 1 2 3 4 012345678901234567890123456789012345678901234-Zhang Hai Math Dept F 1.86 19730826 19970915 Wang Jun Math Dept F 1.81 19650921 19960131 Zhou Ling Math Dept M 1.61 19740301 19970915 整个文件内容,共 5 行Wang Jing Math Dept F 1.75 19720521 19960214 Zhang Yun Math Dept M 1.71 19740911 199709
17、15 -每行 45 个正文字符加上2 个字符(rn)。整个文件5 行,共 47x5=235 字符,或 233,最后可能无回车和换行符,依赖于写文件是是否写它们。注意,数据之间用一个空格符分界。在以下每一例的程序中,应包含下述语句(例中不再写出):#include FILE*fp;Char FileName20=“Students.txt”;例 1.用 fputc()函数创建Students.txt文件:#include /*For strcat()*/main()char StArr547=Zhang Hai Math Dept F 1.86 19730826 19970915n,Wang J
18、un Math Dept F 1.81 19650921 19960131n,Zhou Ling Math Dept M 1.61 19740301 19970915n,Wang Jing Math Dept F 1.75 19720521 19960214n,Zhang Yun Math Dept M 1.71 19740911 19970915n ;/*Note:AtArri45=n ,StArri46=0 (初始化时自动补 0)*/int i,k;char c;fp=fopen(FileName,“w”);/*建新文件,Text mode*/*如果 Binary mode“wb”,初值中
19、的 n 应当换成 rn,StArr548。其他语句均不变。*/if(fp=NULL)printf(Cannot create the new file.n);exit(0);for(i=0;i5;i+)for(k=0;(c=StArrik)!=0;k+)fputc(c,fp);/*写 StArrik*/if(fclose(fp)!=0)/*关闭文件,成功时为0*/printf(Cannot close the file.n);else printf(“n%s”,strcat(FileName,was created.);例 2.用 fgetc()函数读 Students.txt文件:本例把 S
20、tudents.txt文件的第 i 行(以n 结尾)读到 StArr数组的第 i 行 StArri中,且补 0 。main()char StArr10050;int i,k;char c;fp=fopen(FileName,“r”);/*读文件,Text mode*/*在 Text mode,文件中的 rn读成 n*/*如果 Binary mode“rb”,文件中任何字符均不变地被读入。*/i=0;k=0;while (c=fgetc(fp)!=EOF&i100)StArrik=c;/*读入 StArrik*/k+;if(c=n)StArrik=0;i+;k=0;/*行尾补 0*/fclose
21、(fp);/*关闭文件*/写一串字符(字节):int fputs(char*s,FILE*Fp);该函数把以 0 结尾的字符串s 写到Fp文件中,从当前位置开始。但最后的0 不写。写成功时返回写入的最后字符,出错时返回EOF。读一串字符(字节):char*fgets(char*s,int n,FILE*Fp);该函数把Fp文件当前位置开始的(至多)n-1 个字符读到字符数组s 中,如果遇到r ,则跳过不计它。但若遇到n ,即使还不到n-1 个,则在把 n 读到 s 中后,也不再读了。最后在s 中补上 0 后,fgets()返回,返回值也是指向s 的指针。如果在上述读的过程中,发生错误或先遇到文
22、件尾,则返回NULL 此时你须用 feof(Fp)或 ferror(Fp)才能判断是遇到文件尾还是出错。例 3.用 fputs()函数创建Students.txt文件:main()char StArr547=。;/*初始化同例1*/int i;fp=fopen(FileName,“w”);/*建新文件,Text mode*/*如果 Binary mode“wb”,初值中的 n 应当换成 rn,StArr548。其他语句均不变。*/for(i=0;i5;i+)fputs(StArri,fp);/*写 StArri*/fclose(fp)/*关闭文件*/例 4.用 fgets()函数读 Stude
23、nts.txt文件:char StArr10050;fp=fopen(FileName,“r”);/*读文件,Text mode*/i=0;while(fgets(StArri,50,fp)!=NULL&i=1。每一个结构体相当于一个“记录”。用 fwrite()写到文件上的数据通常可以用fread()读回来。例 5.用 fwrite()函数创建Students.dat文件(Binary):Students.txt是 ASCII 文件,但在程序中,学生的身高通常用浮点数 类型,以便用于计算,如计算学生的平均身高等。显然,用Struct类型来描述学生的信息是合理的。我们将从 Students.t
24、xt文件读出学生信息,并把字符形式的身高转换为float形式。然后,再用 fwrite()输出,创建 Students.dat二进制文件。最后再用fread()读出,并 check 结果。#include /*double atof(char*)*/#include /*strcpy(char*,char*)*/#include FILE*fp;char FileName120=Students.txt;char FileName220=Students.dat;struct STUD char StName11,DeptName10;char Sex;float Height;char Bo
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 语言 文件 存取
![提示](https://www.taowenge.com/images/bang_tan.gif)
限制150内