




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、 第十二章 文 件 $12.1 文件概述 文件(file)是程序设计中一个重要的概念。所谓“文件”一般指:存储在外部介质上数据的集合,一批数据是以文件的形式存放在外部介质(如磁盘)上的。 操作系统是以文件为单位对数据进行管理的,也就是说,如果想找存在外部介质上的数据,必须先按文件名找到所指定的文件,然后再从该文件中读取数据。向外部介质上存储数据也必须先建立一个文件(以文件名标识),才能向它输出数据。 以前各章中我们所用到的输入和输出,都是以终端为对象的,即从终端键盘输入数据,运行结果输出到终端上。 从操作系统的角度,每一个与主机相联的输入输出设备都看作是一个文件。 例如,终端键盘是输入文件,显
2、示屏和打印机是输出文件。 在程序运行时,常常需要将一些数据(运行的最终结果或中间数据)输出到磁盘上存放起来,以后需要时再从磁盘中输入到计算机内存。这就要用到磁盘文件。 语言把文件看作是一个字符(字节)的序列,即由一个一个字符(字节)的数据顺序组成。根据数据的组织形式,可分为ASCII文件和二进制文件。ASCII文件又称文本(text)文件,它的每一个字节放一个ASCII代码,代表一个字符。二进制文件是把内存中的数据按其在内存中的存储形式原样输出到磁盘上存放。例如:整数,在内存中占个字节,如果按ASCII形式输出,则占个字节,而按二进制形式输出,在磁盘上只占个字节。用ASCII码形式输出与字符一
3、一对应。 (00100111 00010000 )2 =213+210+29+28 一个字节代表一个字符,因而便于对字符进行逐个处理,也便于输出字符。但一般占存储空间较多,而且要花费转换时间(二进制形式与ASCII码间的转换)。用二进制形式输出数值,可以节省外存空间和转换时间,但一个字节并不对应一个字符,不能直接输出字符形式。一般中间结果数据需要暂时保存在外存上以后又需要输入到内存的,常用二进制文件保存。 由前所述,一个文件是一个字节流或二进制流。它把数据看作是一连串的字符(字节),而不考虑记录的界限。换句话说,语言中文件并不是由记录(record)组成的(这是和PASCAL或其它高级语言不同
4、的)。 在C语言中对文件的存取是以字符(字节)为单位的。输入输出的数据流的开始和结束仅受程序控制而不受物理符号(如回车换行符)控制。我们把这种文件称为流式文件。语言允许对文件存取一个字符,就增加了处理的灵活性。 在过去使用的版本(如系统下使用的)有两种对文件的处理方法:一种叫“缓冲文件系统”,一种叫“非缓冲文件系统”。所谓缓冲文件系统是指:磁盘数据区缓冲区缓冲区 系统自动地在内存区为每一个正在使用的文件名开辟一个缓冲区。从内存向磁盘输出数据必须先送到内存中的缓冲区,装满缓冲区后才一起送到磁盘去。如果从磁盘向内存读入数据,则一次从磁盘文件将一批数据输入到内存缓冲区(充满缓冲区),然后再从缓冲区逐
5、个地将数据送到程序数据区(给程序变量)。缓冲区的大小由各个具体的版本确定,一般为字节。 所谓“非缓冲文件系统”是指系统不自动开辟确定大小的缓冲区,而由程序为每个文件设定缓冲区。 在UNIX系统下,用缓冲文件系统来处理文本文件,用非缓冲文件系统处理二进制文件。用缓冲文件系统进行的输入输出又称为高级(或高层)磁盘输入输出(高层I/O),用非缓冲进行的输入输出又称为低级(低层)输入输出系统。年S 标准决定不采用非缓冲文件系统,而只采用缓冲文件系统。即既用缓冲文件系统处理文本文件,也用它来处理二进制文件。也就是将缓冲文件系统扩充为可以处理二进制文件。 在语言中,没有输入输出语句,对文件的读写都是用库函
6、数来实现的。 A规定了标准输入输出函数,用它们对文件进行读写。 本章主要介绍 的文件系统以及对它的读写。考虑到目前广泛使用的版本中仍常用到非缓冲文件系统,我们也准备对它有关的内容作简要的介绍。但是希望读者尽可能不要采用不符合S 标准的那些部分,否则将使程序可移植性降低。 $文件类型指针 缓冲文件系统中,关键的概念是“文件指针”。每个被使用的文件都在内存中开辟一个区,用来存放文件的有关信息(如文件的名字、文件状态及文件当前位置等)。这些信息是保存在一个结构体类型的变量中的。该结构体类型是由系统定义的,取名为 FILE,有的版本在stdio.h文件中有以下的类型定义: typedef struct
7、 _;*文件号* _;*缓冲区中剩下的字符* _d; 文件操作模式* * _;*下一个字符位置* * _;*文件缓冲区位置* FILE ; 有了FILE类型之后,可以用它来定义若干个FILE类型的变量,以便存放若干个文件的信息。例如,可以定义以下FILE类型的数组。 FILE _efilemaxfile 定义了一个结构体数组_efile,它有maxfile个元素,maxfile是一个符号常量,它的值是可使用的文件的最大数目。 可以定义文件型指针变量。如 FILE *fp; fp是一个指向FILE类型结构体的指针变量。可以使fp指向某一个文件的结构体变量,从而通过该结构体变量中的文件信息能够访问
8、该文件。也就是说,通过文件指针变量能够找到与它相关的文件。如果有个文件,一般应设个指针变量(指向类型 结构体的指针变量),使它们分别指向个文件(确切他说,指向该文件的信息结构体),以实现对文件的访问。$文件的打开与关闭 和其它高级语言一样,对文件读写之前应该“打开”该文件,在使用结束之后应关闭该文件。1 文件的打开(fopen函数) S 规定了标准输入输出函数库,用fopen( )函数来实现打开文件。fopen函数的调用方式通常为: *; fp fopen(文件名,使用文件方式); 例如 fp fopen(”A1”,”) 要打开名字为的文件,使用文件方式为“读入”,fopen函数带回指向A1文
9、件的指针并赋给fp,这样fp就和 A1相联系了,或者说,fp指向A1文件,可以看出, 在打开一个文件时,通知给编译系统以下三个信息:需要打开的文件名,也就是准备访问的文件的名。使用文件的方式(读还是写等)。让哪一个指针变量指向被打开的文件。 使用文件的方式 r rb r+ rb+ w wb w+ wb+ a ab a+ ab+说明: 1用”方式打开的文件只能用于向计算机输入而不能用作向该文件输出数据,而且该文件应该已经存在,不能用”方式打开一个并不存在的文件(即输入文件),否则出错。 用”方式打开的文件只能用于向该文件写数据,而不能用来向计算机输入。如果原来不存在该文件,则在打开时新建立一个以
10、指定名字命名的文件。如果原来已存在一个以该文件名命名的文件,则在打开时将该文件删去,然后重新建立一个新文件。 如果希望向文件末尾添加新的数据(不希望删除原有数据),则应该用“”方式打开。但此时该文件必须已存在,否则将得到出错信息。打开时,位置指针移到文件末尾。 用”+”、”+”、”+”方式打开的文件可以用来输入和输出数据。用”十”方式时该文件应该已经存在,以便能向计算机输入数据。用“十”,方式则新建立一个文件,先向此文件写数据,然后可以读此文件中的数据。用”方式打开的文件,原来的文件不被删去 如果不能实现”打开”的任务,fopen函数将会带回一个出错信息。出错的原因可能是:用”方式打开一个并不
11、存在的文件;磁盘出故障; 磁盘已满无法建立新文件等。此时fopen函数将带回一个空指针值 (在stdio.h文件中已被定义为)。 常用下面的方法打开一个文件: if(fp=fopen(“file1”,”)=L) printf(”canot open this file“); exit(0); 即先检查打开有否出错,如果有错就在终端上输出”cannot open this file“。exit函数的作用是关闭所有文件,终止正调用的过程。待程序员检查出错误,修改后再运行。 用以上方式可以打开文本文件或二进制文件,这是A 的规定,用同一种缓冲文件系统来处理文本文件和二进制文件。但目前使用的有些编译系
12、统可能不完全提供所有这些功能(例如有的只能用”r”,”, ”方式),有的版本不用”+”,、”+”、”+”而用”w”、”wr”、”ar”等,请读者注意所用系统的规定。 在用文本文件向计算机输入时,将回车换行符转换为一个换行符,在输出时把换行符转换成为回车和换行两个字符。在用二进制文件时,不进行这种转换,在内存中的数据形式与输出到外部文件中的数据形式完全一致,一一对应。 在程序开始运行时,系统自动打开三个标准文件:标准输入、标准输出、标准出错输出。通常这三个文件都与终端相联系。因此以前我们所用到的从终端输入或输出,都不需要打开终端文件。 系统自动定义了三个文件指针stdin、stdout和stde
13、rr,分别指向终端输入、输出、出错输出(也从终端输出)。如果程序中指定要从stdin所指的文件输入数据,就是指从终端键盘输入数据。 文件的关闭(fclose函数) 在使用完一个文件后应该关闭它,以防止它再被误用。“关闭”,就是使文件指针变量不再指向该文件,也就是文件指针变量与文件”脱钩”,此后不能再通过该指针对其相连的文件进行读写操作,除非再次打开,使该指针变量重新指向该文件。 用fclose函数关闭文件。fclose函数调用的一般形式为 fclose(文件指针); 例如 fclose(); 用fopen函数打开文件时所带回的指针赋给了fp,今把该文件关闭。 应该养成在程序终止之前关闭所有使用
14、的文件的习惯,如果不关闭文件将会丢失数据。 因为,如前所述,在向文件写数据时,是先将数据输到缓冲区,待缓冲区充满后才正式输出给文件。如果当数据未充满缓冲区而程序结束运行,就会将缓冲区中的数据丢失。用fclose函数关闭文件,可以避免这个问题,它先把缓冲区中的数据输出到磁盘文件然后才释放文件指针变量。 fclose函数也带回一个值:当顺利地执行了关闭操作,则返回值为;如果返回值为非零值,则表示关闭时有错误。这一点可以用ferror函数来测试。 ferror(fp)为0表示未出错,否则表示出错。 $.文件的读写 文件打开之后,就可以对它进行读写了。常用的读写函数如下。 .1 fputc函数和fge
15、tc函数(putc函数和getc 函数) fputc函数把一个字符写到文件上去。其一般形式为 fputc(ch,fp); 其中ch是要输出的字符,它可以是一个字符常量,也可以是一个字符变量。fp是文件指针变量,它从 fopen 函数得到返回值。上面fputc(,fp)函数的作用是将字符(ch的值)输出到 fp 所指向的文件上去。fputc 函数也带回一个值:如果输出成功则返回值为输出的字符;若输出失败,则返回。 是在stdio.h文件中定义的符号常量,值为-1。 我们在第三章介绍过putchar函数,其实putchar函数是从fputc函数派生出来的。putchar()是用 定义的宏,即: #
16、define putchar( c ) fputc(c,stdout) 前面已叙述,stdout是系统定义的文件指针变量,它与终端输出相连。fputc(,stdout)的作用是将的值输出到终端。 fgetc函数 从指定文件读入一个字符,该文件必须是以读或读写方式打开的。 fgetc函数的调用形式为 chfgetc(fp); fp为文件型指针变量,ch为字符变量。fgetc函数带回一个字符,赋给ch。如果在执行fgetc读字符时遇到文件结束符,函数返回一个文件结束标志 EOF,EOF 在stdio.h中定义为-1。如果想从一个磁盘文件顺序读入字符并在屏幕上显示出来,可以: chfgetc(fp)
17、; ile(ch!=EOF) putchar(ch); chfgetc(fp); 注意:不是可输出字符,因此不能在屏幕上显示。由于字符的码不可能出现-,因此定义为-1是合适的。当读入的字符值等于-(即时,表示读入的已不是正常的字符而是文件结束符。但以上只适用于读文本文件的情况。现在 已允许用缓冲文件系统处理二进制文件,而读入某一个字节中的二进制数据的值有可能是-,而这又恰好是的值。这就出现了需要读人有用数据而却被处理为”文件结束”的情况。为了解决这个问题, 提供一个feof函数来判断文件是否真的结束。feof(fp)用来测试 fp 所指向的文件当前状态是否”文件结束”。如果是文件结束,函数fe
18、of(fp)的值为(真),否则为(假)。 如果想顺序读入一个二进制文件中的数据,可以用: (!feof(fp) =fgetc(fp); 这种方法也适用于文本文件。和函数使用举例 在掌握了以上几种函数以后,可以编制一些简单的使用文件的程序。 例从键盘输入一些字符,逐个把它们送到磁盘 上去,直到输入一个”#”,为止。 include “stdio.h” main() FILE *fP; char ch,filename; scanf(”,filename); if(fpfopen(filename,”“)=) printf(”cannot open file”);exit(0); chgetcha
19、r(); while(ch!=”#”) fputc(ch,fp);putchar(ch);chgetchar(); fclose(fp); 运行情况如下: (输入磁盘文件名) (输入一个字符串) (输出一个字符串) 文件名由键盘输入,赋给字符数组,在p函数中第一个参数“文件名”可以直接写成字符串常量形式(如”,也可以用字符数组名,在字符数组中存放文件名(如本例所用的方法)。本例运行时,从键盘输入磁盘文件名”.c”,然后输入要写入该磁盘文件的字符” ”,#是表示输入结束,程序将” ”写到以”命名的磁盘文件中,同时在屏幕上显示这些字符,以资核对。 可以将文件中的内容打印出来: Ctype file
20、1.c 例将一个磁盘文件中的信息复制到另一个磁盘 文件中。 include “stdio.h” main() FILE *in,*out; char ch,infile10,outfile10; printf(”enter the infilename:n”) scanf(,infile); printf(”enter the outfilename:n”); scanf(,outfile) if(infopen(infile,”r”)=) printf(” cannot open infilen”);exit(0); if(outfopen(outfile,”)=) printf(” can
21、not open outfilen”);exit(0); hile(!feof(in) fputc(fgetc(in),out); fclose(in);fclose(out); 运行情况如下: : (输入原有磁盘文件名) : (输入新复制的磁盘文件名) 程序运行结果是将.c文件中的内容复制到.c中去。可以用下面命令验证: tp .c (.中的信息) ct .c (.c中的信息) 以上程序是按文本文件方式处理的。也可以用此程序来复制一个二进制文件,只需将两个fopen函数中的”和”分别改为rb和即可。 也可以在输入命令行时把两个文件名一起输入。这时要用到函数的参数。程序可改为:include
22、“stdio.h”main(int argc,char* argv) FILE *in,*out; char ch, if( argc!=3) printf(”you forgot to enter a filename”); exit(0); if(infopen(argv1,) printf(” cannot open infilen”);exit(0); if(outfopen(argv2,“”)=) printf(” cannot open infilen”);exit(0); hile(!feof(in) fputc(fgetc(in),out); fclose(in);fclose
23、(out); 最后说明一点:因为在stdio.h中有定义:define putc(ch,fp) fputc(ch,fp)define getc(fp) fgetc(fp)由此,用getc和fgetc是一样的,而用putc和fputc是一样的。 12.4.2 fread函数和fwrite函数 用getc和putc函数可以用来读写文件中的一个字符。但是常常要求一次读入一组数据(例如,一个实数或一个结构体变量的值),在ANSI C标准中,fread和fwrite函数,可用来读写一个数据块。它们的一般调用形式为: fread(buffer,size,count,fp); fwrite(buffer,s
24、ize,count,fp); 其中: buffer:是一个缓冲区指针。对fread来说,它是读入数据 存放的起始地址。对fwrite来说,它是要输出数据存放的起始的地址(以上指的是起始地址)。 size: 要读写的字节数。 count: 要进行读写多少个size字节的数据项。 fp:文件型指针。如果文件以二进制形式打开,用fread和fwrite函数就可以读写任何类型的信息,如: fread(f,4,2,fp);其中f是一个实型数组名。一个实型变量占4个字节。这个函数从fp所指向的文件读入2次(每次4个字节)数据,存储到数组f中。 如果有一个如下的结构体类型: struct student_t
25、ype char name10; int num; int age; char addr30; stud40;结构体数组stud有40个元素,每一个元素用来存放一个学生的数据(包括姓名、学号、年龄、地址)。 假设学生的数据已存放在fn所指的磁盘文件中,可以用下面的for句和fread函数读人40个学生的数据: for(i=0;i40;i+) fread(&studi,sizeof(struct student_type),1,fn); 同样,以下for语句和fwrite函数可以将内存中的学生数据输出到磁盘文件中去。 for(i=0;i40,i+) fwrite(&studi,sizeof(st
26、ruct student_type),1,fn); 如果fread或fwrite调用成功,则函数返回值为count的值,即输入或输出数据项的完整个数。 下面写出一个完整的程序。 例123从键盘输入4个学生的有关数据,然后把它们转存到磁盘文件上去。 #include stdio.h” #define SIZE 4 struct student_type char name10; int num; int age; char addr15; studSIZE; void save() FILE *fp; int i; if(fp=fopen(”stu_list”,”wb“)=NULL) print
27、f(”cannot open filen); return; ; for(i=0;iSIZE;i+) if(fwriie(&studi,sizeof(struct student_type),1,fp)!=1) printf(”file write errorn); main()int i; for(i=0;iSIZE;i+)scanf(%s%d%d%s,,&studi.num,&studi.age,studi.addr); save(); 在main函数中,从终端键盘输入4个学生的数据,然后调用save函数.程序运行时,屏幕上并无输出任何信息,只是将从键盘输入的数据送到磁
28、盘文件上。为了验证在磁盘文件”stu_1ist”中是否已存在此数据,可以用以下程序从”stu_list”文件中读人数据,然后在屏幕上输出。 #include ”stdio.h #define SIZE 4 struct student_type char name10 int num; int age; char addr15; stud SIZE; main() int i; FILE *fp; fp=fopen(”stu_1ist”,”rb”); for(i=0;iSIZE;i+) fread(&studi;sizeof(struct student_type),1,fp); printf
29、(”%-10s%4d%4d%-15sn,, studi.num,studi.age,stud1.addr); 程序运行时不需从键盘输入任何数据。屏幕显示出以下信息: zhang 1001 19 room_l01 fun 1002 20 room_102 tan 1003 21 room_103 ling 1004 21 room_104 请注意输入输出数据的状况。从键盘输入个学生的数据是ASCII码,也就是文本文件。在送计算机内存时,回车和换行符转换成一个换行符。再从内存以“w”方式(二进制写)输出到“stu_list”文件,此时不发生字符转换,按内存中存储形式原样输出到磁
30、盘文件上。在上面验证程序中,又用fread函数从“stu_list”文件向内存读入数据,注意此时用的是“r”方式,即二进制方式,数据按原样输入,也不发生字符转换。 也就是这时候内存中的数据恢复到第一个程序向“stu_list”输出以前的情况。最后在验证程序中,用printf函数输出到屏幕,printf是格式输出函数,输出ASCII码,在屏幕上显示字符。换行符又转换为回车加换行符。如果企图从“stu_list”文件中以“r”方式读人数据就会出错。fread和fwrite函数一般用于二进制文件的输入输出。因为它们是按数据块的长度来处理输入输出的,在字符发生转换的情况下很可能出现与原设想的情况不同。
31、例如,如果写fread(&studi,sizeof(struct student_type),1,stdin);企图从终端键盘输入数据,这在语法上并不存在错误,编译能通过。如果用以下形式输入数据: zhang _101由于fread函数要求一次输入个字节(而不问这些字节的内容),因此输入数据中的空格也作为输入数据而不作为数据间的分隔符了。连空格也存储到studi中了,显然是不对的。 这个题目要求的是从键盘输入数据,如果已有的数据自已以二进制形式存储在一个磁盘文件stu_dat”中,要求从其中读入数据并输出到stu_list文件中,可以编写一个load函数,从磁盘文件中读二进制数据。 void
32、load() FILE *fp; int i; if(fp=fopen(stu_dat”,rb)=NULL) printf(“cannot open infilen”); return; for (i=0;iSIZE;i+) if(fread(&studi,sizeof(struct student_type),1,fp)!=1) if(feof(fp) return; else printf(file read errorn);exit(0); 将load函数加到本题原来的程序文件中,并将i函数改为: () load(); save(); 即可实现题目要求。 由于ANSIC标准决定不采用非缓
33、冲输入输出系统,所以在缓冲系统中增加了fread和fwrite两个函数,用来读写一个数据块。有些目前使用的编译不具备这两个函数,请读者注意。12.4.3 fprintf函数和fscanf函数 fprintf函数、fscanf函数与printf函数、scanf函数作用相仿,都是格式化读写函数。只有一点不同:fprintf和fscanf函数的读写对象不是终端而是磁盘文件。一般调用方式为:fprintf(文件指针,格式字符串,输出表列);fscanf(文件指针,格式字符串,输入表列);例如 fprintf(fp,%d,%6.2f,i,t);它的作用是将整型变量i和实型变量t的值按%d和%6.2f的格
34、式输出到fp指向的文件上。同样,用以下fscanf函数可以从磁盘文件上读入ASCII字符:fscanf(fp,%d,%f,&i,&t);磁盘文件上如果有以下字符: 3,4.5则将磁盘文件中的数据3送给变量i,4.5送给变量t。 用fprintf和fscanf函数对磁盘文件读写,使用方便,容易理解,但由于在输入时需要将ASCII码转换为二进制形式,在输出时又要将二进制形式转换成字符,花费时间比较多。因此,在内存与磁盘频繁交换数据的情况下,最好不用fprintf和fscanf函数,而用fread和fwrite函数。 12.4.4其它读写函数 一、putw和getw函数 大多数C编译系统都提供另外两
35、个函数:putw和getw,来对磁盘文件读写一个字(整数)。例如 putw(10,fp);它的作用是将整数10输出到fp指向的文件。而 i=getw(fp);的作用是从磁盘文件读一个整数到内存,赋给整型变量i。如果所用的C编译的库函数中不包括putw和getw函数,可以自己定义该二函数。putw函数如下: putw(int i, FILE * fp) char *s; s=&i; putc(s0,fp);putc(s1,fp); return(i); getw函数如下:getw(FILE *fp)char *s; int i; s=&i; /*使s指向i的起始地址*/ s0=getc(fp);
36、 s1=getc(fp); return(i); putw和getw并不是ANSI C标准定义的函数。但许多C编译都提供这两个函数(例如Microsoft4.0有putw和getw函数),但有的C编译可能不以putw和getw命名此两函数,而用其它函数名,请用时注意。 类似可以写出 putfloat,和 getfloat等函数。 三、fgets函数和fputs函数 fgets的作用是从指定文件读入一个字符串。如 fgets(str,n,fp); 从fp指向的文件输入n-1个字符,并把它们放到字符数组str中。如果在读入n-1个字符结束之前遇到换行符或EOF,读入即结束。字符串读入后在最后加一个
37、0字符,fgets函数返回值为str的首地址。 fputs函数的作用是向指定的文件输出一个字符串。如 fputs(China”,fp); 把字符串China”,输出到fp指向的文件。fputs函数中第一个参数可以是字符串常量、字符数组名或字符型指针。输出成功,函数值为0;失败时,为非零值。 这两个函数类似以前介绍过的gets和puts函数,只是fgets和fputs函数以指定的文件作为读写对象. 12.5 文件的定位 文件中有一个位置指针,指向当前读写的位置。如果顺序读写一个文件,每次读写一个字符,则读写完一个字符后,该位置指针自动移动指向下一个字符位置。如果想改变这样的规律,强制使位置指针指
38、向其它指定的位置,可以用有关函数。 12.5.1 rewind函数 rewind函数的作用是使位置指针重新返回文件的开头。此函数没有返回值。 例12.4 有一个磁盘文件,第一次使它显示在屏幕上,第二次把它复制到另一文件上。 #include stdio.h main()FILE *fp1,*fp2; fp1=fopen(file1.C,r); fp2=fopen(file2.C,w); while(!feof(fp1)putchar(getc(fp1); rewind(fp1); while(!feof(fp1)putc(getc(fp1),fp2); fclose(fp1); fclose(
39、fp2); 在第一次显示在屏幕以后,文件file1.c的位置指针已指到文件末尾,feof的值为非零(真)。执行rewind函数,使文件的位置指针重新定位于文件开头,并使feof函数的值恢复为0(假)。 fs函数和随机读写 对流式文件可以进行顺序读写,也可以进行随机读写。关键在于控制文件的位置指针,如果位置指针是按字节位置顺序移动的,就是顺序读写。如果可以将位置指针按需要移动到任意位置,就可以实现随机读写。所谓随机读写,是指读写完上一个字符(字节)后,并不一定要读写其后续的字符(字节),而可以读写文件中任意所需的字符(字节)。 用fseek函数可以实现改变文件的位置指针。 fseek函数的调用形
40、式为 fseek(文件类型指针,位移量,起始点) “起始点”用0,1或2代替,0代表“文件开始”,1为“当前位置”, 为“文件末尾”。ANSI C标准指定以下的名字: 起始点 名字 用数字代表 文件开始 SEEK_SET 0 文件当前位置 SEEK_CUR 1 文件末尾 SEEK_END 2 fseek(文件类型指针,位移量,起始点) ANSI C和大多数C版本要求位移是long型数据。 fseek函数一般用于二进制文件,因为文本文件要发生字符转换,计算位置时往往会发生混乱。 下面是函数调用的几个例子: fseek(fp,100L,0);将位置指针移到离文件头100个字节处。 fseek(fp
41、,50L,1);将位置指针移到离当前位置50个字节处。 fseek(fp,-,);将位置指针从文件末尾处向后退个字节。 利用fseek函数就可以实现随机读写了。 例12.5在磁盘文件上存有10个学生的数据。要求将第.9.个学生数据输入计算机,并在屏幕上显示出来。 程序如下: #include “stdio.h struct student_type char name10; int num; int age; char sex; stud10; main() int i; FILE *fp; if(fp=fopen(“stud_dat”,“rb”)=NULL) printf(ca
42、nnot open filen); exit(0); for(i=0;i10;i+=2)fseek(fp,i*sizeof(srtuct student_type),0); fread(&studi,sizeof(srtuct student_type), 1,fp); printf(%s%d%d%cn,, studi.num,studi.age,studisex); fclose(fp); . ftell函数 ftell函数的作用是得到流式文件中的当前位置,用相对于文件开头的位移量来表示。由于文件中的位置指针经常移动,人们往往不容易辨清其当前位置。用ftell函数可以得到
43、当前位置。如果ftell函数返回值为:-1L,表示出错。例如: ftll(fp); if(i=-1L)printf(“error”); . 出错的检测 C标准提供一些检查输入输出函数调用中的错误。 1261 ferror函数 在调用各种输入输出函数时,如果出现错误,除了函数返回值有所反映外,还可以用ferror函数检查。它的一般调用形式为 ferror(fp); 如果ferror返回值为(假),表示未出错。如果返回一个非零值,表示出错。应该注意,对同一个文件每一次调用输入输出函数,均产生一个新的ferror函数值,因此,应当在调用一个输入输出函数后立即检查ferror函数的值,否则信息会丢失。
44、 在执行fopen函数时,ferror函数的初始值自动置为. 12.6.2 clearerr函数 它的作用是使文件错误标志和文件结束标志置为。假设在调用一个输入输出函数时出现错误,ferror函数值为一个非零值。在调用clearerr(fp)后,ferror(f)的值变成。 只要出现错误标志,就一直保留,直到对同一文件调用clearerr函数或rewind函数,或任何其它一个输入输出函数。 S 非缓冲文件系统 非缓冲文件系统不属于ANSI 标准规定的范围,但是目前在许多系统中使用比较多,因此在本节中只作简单介绍。目的只是使读者在阅读已有的程序中不致感到困难,但希望读者不要在新编写的程序中用非缓
45、冲文件系统,以免移植程序时出现问题。 缓冲输入输出系统又称高级磁盘输入输出系统。非缓冲输入输出系统又称为低级磁盘输入输出系统,系统不为这类文件自动提供文件缓冲区,程序设计者必须自己设定一个缓冲区并考虑如何使用它们。非缓冲文件系统提供了一些输入输出函数,用于对这类文件进行输入输出操作。 缓冲文件系统(高级I/O系统)是有文件指针的,通过文件指针访问文件, 而非缓冲文件系统(低级磁盘I/O系统)则没有文件型指针,不是靠文件指针来访问文件,而是用一个整数代表一个文件(相当于FORTRAN等语言的“文件号”),这个整数称为“文件说明符”。通过下面介绍的几个常用函数可以对这种方式有一大概的了解. . o
46、pen函数 用来打开一个非缓冲文件。它的一般形式为 open(文件名,打开方式) 打开方式指该文件打开后的工作方式,即读写方式。 方式 作用 只能读 1 只能写 可以读写 例如,open(”_”,),打开一个名为“_”的文件,只能用于输入。 如果打开成功,open函数返回一个正整数;如果文件因故未能打开,则返回一。函数一般是这样使用的(设fd已定义为整型变量): if(fd=open(A,1)一) ( open n); (); 如果要打开的文件不存在,多数编译系统按“打开失败”处理,不产生新的文件。但有的编译系统可以用open函数建立一个新文件。例如,上面的打开操作中,如果原来磁盘上不存在一个
47、名为的文件,则 open函数建立一个名为”的文件,可供写数据。另一些编译系统则只能用函数建立一个新文件。 函数 用来关闭已打开的文件,其调用形式为 close(fd);fd用为整型变量,它是”文件说明符”(即文件号)。在打开文件时,函数返回一个整数,这就是文件说明符(文件号)。在未关闭此文件之前,此文件说明符与该文件相联系,或者说,它代表一个确定的文件。执行函数后,文件号释放,它不再与一个确定的文件相联系。它可以再被用来与另一文件相联系。文件号是由系统在打开文件时分配的,而不是由程序设计者指定的。每一个编译系统规定了可以同时打开的文件的最大数字。假如某一编译系统允许同时最多打开个文件,则的值为
48、。如果用函数关闭了为的文件,则再用open函数打开另一文件时,系统就可能将作为该新文件的文件号。可以看到文件号先后与两个不同的文件相联系。 由于一个编译系统允许同时打开的文件数目是有限的。因此,凡不再使用的文件应及时用函数关闭。 如果关闭操作失败(如不存在此文件,或把磁盘从驱动器取出),则函数返回一;成功时返回零。 .3 creat函数 有的编译系统(例如 C)不允许用open函数建立一个新文件,它提供函数用来建立新文件。其调用形式为 (文件名,打开方式);它返回一个整数文件号。例如 =(“”,);使用函数时请查阅系统使用手册。 , 函数 函数的作用是从指定的磁盘文件中读入若干个字符到程序开辟
49、的缓冲区中。其形式为 (,);其中为文件号,是一个地址,它指向程序员指定的”缓冲区”的开头,这个”缓冲区”可 以是一个数组或一个变量,或一个已分配内存的数据结构。是一个整数。上述函数的作用是从所代表的文件中,读个字节的信息到指向的缓冲区中,如果执行成功,则函数返回实际读入的字节数;若遇文件结束则函数值返回;若有错,祷匾唬薄 下面的程序从名为a1的文件中读个字符到数组中,并将该字符串显示出来。 例6 () ; ; if(a1,)=一) (cannot n”); (0); (,)!) printf(read error); (%sn”,); cl(); f是一个字符型数组,它就是程序设计者指定的”缓冲区”,这个“绥冲区”不是系绞自动设置的(这是与缓冲文件系统不同的),而是由程序设计者根据需要在程序中设定的。如果程序不设定所需的”缓冲区”,数据就无法读入。其实,也可以简单地理解为:将数据读入到指定地址的内存单元中去。如同郧敖樯芄模螅悖幔睿婧茄 (“”,);只是函数从磁盘文件中读数据,因此要指定,而且要指定需读入的字节数目。 在上述程序中,如果成功地执行了,则函数的返回值应为。如果不等于,则肯定出现意外情况(例如,企图从一个只能写的文件中读数;文件中能被读入的字节不足;等等)。 在执行函数过程中,每读入一个字节后,文件位置指针往后移到下一个字节处。每次从文件位置指针指向处开始读取数据。
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 【正版授权】 IEC 63584:2024 EN Open Charge Point Protocol (OCPP)
- 公司装修合同正规
- 浴场承包合同
- 电脑维护保养合同
- 公立医院职工购房借款合同
- 化粪池设备销售合同
- 房地产物业售楼处服务合同
- 场地房屋租赁服务合同
- 担保借款三方合同
- 挡土墙施工承包合同
- 2025年南通科技职业学院高职单招职业适应性测试近5年常考版参考题库含答案解析
- 人工智能与机器学习在风险管理中的应用-深度研究
- 河南省洛阳市伊川县2024-2025学年上学期期末八年级生物试题
- 2025年东营科技职业学院高职单招职业技能测试近5年常考版参考题库含答案解析
- 福建省厦门市2024-2025学年八年级上学期1月期末英语试题(含笔试答案无听力答案、原文及音频)
- 全脊柱x线摄影技术
- 《酸枣营销战略》课件
- 真需求-打开商业世界的万能钥匙
- 三年级数学下册总复习课件
- 仓库礼仪培训
- 2024土方工程承包合同包含进度支付与违约责任条款范本3篇
评论
0/150
提交评论