第 8 章 文 件

31
第8第 第第第第第第第 第第第 第第第第第第第第第 1 / 3 1 C 第第第第第第龙龙龙龙龙 第第第第 第第第 023-66834110

Upload: gannon

Post on 11-Jan-2016

80 views

Category:

Documents


0 download

DESCRIPTION

课件制作:刘达明 023-66834110. 《C 语言程序设计 》 龙昭华主编. 第 8 章 文 件. 第一节 文件的基本概念 第二节 文件操作的相关函数. 1 / 31. ………. n-2. n-1. 1. 2. 3. 4. 0. 结束标志. 课件制作:刘达明 023-66834110. (第八章 文 件). 第一节 文件的基本概念. 一、 C 文件的概念. 所谓 的 “ 文件 ” ( file )一般指: 存储在外部介质上的相关数据的集合 。存放 - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: 第 8 章 文    件

第 8 章 文 件

第一节 文件的基本概念

第二节 文件操作的相关函数

1 / 31

《 C 语言程序设计》 龙昭华主编

课件制作:刘达明 023-66834110

Page 2: 第 8 章 文    件

第一节 文件的基本概念(第八章 文 件)

2 / 31

所谓 “ ”的 文件 ( file)一般指:存储在外部介质上的相关数据的集合。存放文件的外部介质有磁带、磁盘、光盘等外部存储器。数据包括:数字、文字、图形、图象、声音、视频等。在本章所讲的文件是由数字和文字组成的数据文件。 以前各章中所用到的输入输出,都是以屏幕等 ( 标准输出文件指针: stdout)为输出设备,以键盘 ( 标准输入文件指针: stdin) 为输入设备。而程序运行有时需要把数据存放到磁盘中,这就要用到磁盘文件。 C 语言把文件看作是一个字符 ( 字节 ) 的序列,即由一个一个的字符或字节的数据顺序组成。换句话说, C 语言是把每一个文件都看作是一个有序的字节流。

一、 C 文件的概念

0 结束标志n-1n-21 2 3 4 ………

流是文件和程序之间的通道。一个 C 程序可以创建文件和对文件内容进行更新、修改,在程序中所需的数据也可以从另一个文件中获得。 对文件的操作一般通过三个步骤完成:打开文件、读或写文件、关闭文件。

课件制作:刘达明 023-66834110

Page 3: 第 8 章 文    件

二、文件系统

第一节 文件的基本概念

3 / 31

在 C语言中,根据操作系统对文件的处理方式的不同,把文件系统分为缓冲文件系统和非缓冲文件系统。 ANSI C标准采用缓冲文件系统。 缓冲文件系统 ( 又称标准 I/O)是指操作系统在内存中为每一个正在使用的文件开辟一个读写缓冲区。从内存向磁盘输出数据时,必须先送到内存缓冲区,装满缓冲区后才一起送到磁盘去。如果从向内存读入数据,则一次从磁盘文件将一批数据输入到内存缓冲区,然后再从内存缓冲区逐个地将数据送到程序数据区 ( 变量 ) 。

(第八章 文 件)

文件

外存程序数据区

输入缓冲区

输出缓冲区

输入

输出 输出 ( 写 )

输入 ( 读 )

内 存

课件制作:刘达明 023-66834110

Page 4: 第 8 章 文    件

三、文件分类

第一节 文件的基本概念

4 / 31

(第八章 文 件)

缓冲文件系统解决了高速 CPU与低速外存之间的矛盾,使用它延长了外存的使用寿命 ,也提高了系统的整体效率。 非缓冲文件系统 ( 又称系统 I/O) 是指系统不自动开辟确定大小的内存缓冲区 ,而由程序自己为每个文件设定缓冲区。 标准 I/O 与系统 I/O 分别采用不同的输入输出函数对文件进行操作。由于 ANSIC 只采用缓冲文件系统,因此本章所讲的函数也只是处理标准 I/O 的函数。

1 、从用户角度分类 从用户的角度文件分为标准设备文件和普通磁盘文件。 ⑴标准设备文件:是指与主机相连的各种外部设备,如显示器、打印机、键盘等。在操作系统中,把外部设备也看作是一个文件来进行管理,把它们的输入、输出等同于对磁盘文件的读和写。 标准输入文件指针: stdin 。如果指定从 stdin 输入数据,就是键盘输入。 标准输出文件指针: stdout 。如果指定 stdout 输出数据,就是屏幕等输出。 标准错误输出文件指针: stderr 。标准错误输出也是从屏幕终端输出。 ⑵普通磁盘文件:本章所讲的文件主要针对磁盘文件。

课件制作:刘达明 023-66834110

Page 5: 第 8 章 文    件

2 、按文件的编码方式分类

第一节 文件的基本概念

5 / 31

(第八章 文 件)

从文件的编码方式看, C文件分为 ASCII文件和二进制文件。 ⑴ASCII 文件 ( 也称文本文件 ) : ASCII文件在磁盘中存放时,每个字符对应一个字节,用于存放对应的 ASCII码。如:整型十进制数 12345 ,按 ASCII 文件存放则需要占用 5 个字节。可在屏幕上显示,但占用空间较大,读写操作要转换。 ⑵二进制文件:是对不同的数据类型,按其实际占用内存字节数存放。即内存的存储形式,原样输出到磁盘上存放。如:整型十进制数 12345 ,按二进制文件存放只需要 2 个字节。屏幕显示为乱码,但占用空间小,读写操作效率高。

00110000 00111001

00110000 00111001

00110001 00110010 00110011 00110100 00110101

ASCII 文件形式

二进制文件形式

内存存储形式

整数: 12345

1(49) 2(50) 3(51) 4(52) 5(53)转换

直接

课件制作:刘达明 023-66834110

Page 6: 第 8 章 文    件

四、文件指针

第一节 文件的基本概念

6 / 31

要调用磁盘上的一个文件时,必须知道与该文件有关的信息。比如文件名、文件的当前读写位置、文件缓冲区大小与位置、文件的操作方式等。这些信息被 C语言系统保存在一个称作 FILE的结构体中,它在 stdio.h头文件中定义内。FILE 结构体的内容为 ( 在使用文件操作时,一般不用关心 FILE 内部成员信息 ) :typedef struct{ int level; /* 缓冲区“满”或“空”的程度 */ unsigned flags; /* 文件状态标志 */ char fd; /* 文件描述符 */ unsigned char hold; /* 如无缓冲区不读取字符 */ int bsize; /* 缓冲区大小 */ unsigned char *buffer; /* 数据缓冲区位置 */ unsigned char *curp; /* 文件定位指针 */ unsigned istemp; /* 临时文件指示器 */ short token; /* 用于有效性检查 */}FILE;

(第八章 文 件)

课件制作:刘达明 023-66834110

Page 7: 第 8 章 文    件

文件指针 ( 续 ) :

第一节 文件的基本概念

7 / 31

有了结构体 FILE 类型后,可以用它来定义若干个 FILE 类型的变量,以便存放若干个文件的信息。如: FILE f[5]; 定义了一个结构体数组 f ,它有 5 个元素可以用来存放 5 个文件的信息。 对于每一个要操作的文件,都必须定义一个指针变量,并使它指向该文件结构体变量,这个指针称为文件指针。通过文件指针找到被操作文件的描述信息,就可对它所指的文件进行各种操作。定义文件指针的一般形式为: FILE * 指针变量标识符 ;如: FILE *fp; 表示 fp 是一个指向 FILE 类型结构体的指针变量。可以使 fp 指向某一个文件的结构体变量,从而通过该结构体变量中的文件信息能够访问该文件。 如果有 n 个文件,一般应定义 n 个 FILE 类型的指针变量,使它们分别指向 n 个文件所对应的结构体变量。如: FILE *fp1 , *fp2 , *fp2 , *fp4; 可以处理 4 个文件。 注意: FILE 是用 typedef 声明的文件信息结构体的别名,由 C 系统定义,用户只能使用,不能修改,并且 FILE 必须大写。

(第八章 文 件)

课件制作:刘达明 023-66834110

Page 8: 第 8 章 文    件

第二节 文件操作的相关函数(第八章 文 件)

8 / 31

对文件的操作一般步骤包括:打开文件、读或写文件、关闭文件。在C语言中,文件操作都是由库函数来完成的。这些库函数包含在 stdio.h 头文件中。

一、文件的打开与关闭 所谓打开文件,实际上是建立文件的各种有关信息,并使文件指针指向该文件,以便进行其它各种操作。关闭文件则是断开指针与文件之间的联系,也就禁止再对该文件进行操作。 1 、文件的打开 (fopen函数 ) ANSIC 规定了标准输入输出函数库,用 fopen() 函数来实现打开文件。 fopen函数的原型为: FILE *fopen(char *filename,char *mode)其中参数 filename 表示一个文件名,是用双引号括起来的字符串,这个字符串可以是一个合法的带有路径的文件名。参数 mode 表示对文件的操作模式, mode的值仍需要用双引号括起来, mode 的取值及其含义详见教材 P228 的表 8.1 。 如: FIEL *fp1; fp1=fopen(“test.c”,”r”); 表示是在当前目录下打开文件test.c “ ”,只允许进行 读 操作,并使 fp指向该文件。 再如: FIEL *fp2; fp2=fopen(“c:\\tt\\test.exe”,”rb”); 表示打开 C 盘下tt 目录中的 test.exe 文件,是二进制文件,只允许按二进制方式进行读操作。

课件制作:刘达明 023-66834110

Page 9: 第 8 章 文    件

文件使用方式及其意义

第二节 文件操作的相关函数

9 / 31

(第八章 文 件)

ASCII 文件 操作

ASCII 文件 操作

二进制 文件 操作

二进制 文件 操作

只读

只读

只写追加

只写追加读写读写读写读写读写读写

r

w

a

r+

w+

a+

rb

wb

ab

rb+

wb+

ab+

打开一个已经存在的文本文件

打开一个已经存在的二进制文件

建立并打开一个文本文件打开或建立一个文本文件,在末尾写入

建立并打开一个二进制文件打开或建立一个二进制文件,在末尾写入打开一个已经存在的文本文件

打开一个已经存在的二进制文件

建立并打开一个文本文件打开或建立一个文本文件,在末尾写入

建立并打开一个二进制文件打开或建立一个二进制文件,在末尾写入

课件制作:刘达明 023-66834110

Page 10: 第 8 章 文    件

2 、文件的关闭 (fclose 函数 )

第二节 文件操作的相关函数

10 / 31

fcolse 函数的原型为: int fclose(FILE *fp) 功能: “ ” 使文件指针变量与文件 脱钩 ,释放文件结构体和文件指针。

(第八章 文 件)

#include <stdio.h>main(){ FILE * fp; fp=fopen(“test.txt”,”w”); if (fp==NULL) { printf(“file open error! \n”); exit(0); /* 终止程序 */ }else { printf(“file open OK! \n); fclose(fp); }}

返回值:关闭成功时返回 0 。否则(如磁盘空间不足、写保护或关闭已经关闭的文件 )返回 EOF,即 -1。

特别注意,文件使用完后,一定要关闭文件,否则可能丢失数据。因为在关闭之前,首先将缓冲区的数据输出到磁盘文件中,然后再释放文件指针变量。

程序中的 exit 函数原型为: void exit(int status) 功能:终止程序。它将 status 的值发送给 DOS 环境变量。它在 stdlib.h 中声明。

课件制作:刘达明 023-66834110

Page 11: 第 8 章 文    件

二、文件操作错误检测

第二节 文件操作的相关函数

11 / 31

(第八章 文 件)

1 、 feof 函数 函数原型: int feof(FILE *fp) 功能:检查文件是否结束。 返回值:若遇文件结束符,则返回非 0 值。否则返回 0 值。 2 、 ferror 函数 函数原型: int ferror(FILE *fp) 功能:判断文件流上是否有错误。 返回值:若正确,则返回 0 。若发生错误,则返回非零值。注意:对同一个文件在每一次调用输入输出函数 ( 如: putc 、 getc 、 fread 、fwrite 等 ) 时,均产生一个新的 ferror 函数值。因此,应当在调用一个输入输出函数后立即检查 ferror 函数的值,否则信息会丢失。在执行 fopen 函数时,ferror 函数的初始值自动置为 0 。 3 、 clearerr 函数 函数原型: void clearerr(FILE *fp) 功能:使文件错误标志 (ferror 的值 ) 和文件结束标志 (feof 的值 ) 置为 0 。

课件制作:刘达明 023-66834110

Page 12: 第 8 章 文    件

三、顺序文件的读写

第二节 文件操作的相关函数

12 / 31

(第八章 文 件)

文件的顺序读写,是指文件被打开后,按照数据流的先后顺序对文件进行读写操作。每读写一次后,文件指针自动指向下一个读写位置。 1 、单个字符的读写函数 (fgetc 和 fputc) ⑴fgetc 函数(与 getc 一样) 函数原型: int fgetc(FILE *fp) 功能:从 fp 所指向的文件中取得下一个字符。 返回值:若正常,则返回所得到的字符 ASCII 码值。否则读到文件尾 ( 键盘输入时 Ctrl+Z 表示文件结尾)或出错,返回 -1(EOF) 。 注意:前面讲过的 getchar 函数实际上是以下宏定义来实现的: #define getchar() fgetc(stdin) 说明:①在 fgetc函数调用中,读取的文件必须是以读或读写方式打开的。②读取字符的结果也可以不向字符变量赋值,这时读出的字符被丢失。③在文件内部有一个位置指针,用来指向文件的当前读写字节。该指针由系统自动设置,用户不用关心。每执行一次 fgetc 该指针自动下移一个字节,因此 fgetc 可用在循环中读取文件的所有字符。

课件制作:刘达明 023-66834110

Page 13: 第 8 章 文    件

⑵fputc 函数(与 putc 一样)

第二节 文件操作的相关函数

13 / 31

(第八章 文 件)

函数原型: int fputc(int ch, FILE *fp) 功能:把一个字节代码 ch 写入 fp 所指向的文件中。 返回值:若正常,则返回字符 ch 的 ASCII 码值。否则出错,返回 -1(EOF) 。

注意:前面讲过的 putchar 函数实际上是以下宏定义来实现的: #define putchar(ch) fputc((ch),stdout)

说明: ①被写入的文件可以用写、读写、追加方式打开。 ②用写或读写方式打开一个已存在的文件时将清除原有的文件内容,写入字符从文件首开始。 ③如需要保留原有文件内容,希望写入的字符从文件末尾开始存放,必须以追加方式打开文件。 ④被写入的文件若不存在,则自动创建该文件。 ⑤每写入一个字符,文件内部位置指针向后移动一个字节。

课件制作:刘达明 023-66834110

Page 14: 第 8 章 文    件

例 8.1 从键盘输入字符存入文件中,以 # 号结束。

第二节 文件操作的相关函数

14 / 31

(第八章 文 件)

#include <stdio.h>main(){ FILE *fp; char ch,filename[10]; scanf(“%s”,filename); if ((fp=fopen(filename,”w”))==NULL) { printf(“cannot open file!\n”); exit(0); } ch=getchar(); /* 读 scanf 的回车符 */ ch=getchar(); /* 输入第一个字符 */ while(ch!=‘#’) { fputc(ch,fp); putchar(ch); ch=getchar(); } fclose(fp);}

运行情况如下:file.txt ( 回车 )Comput and c# ( 回车 )Comput and c

如果需要从文件读入字符然后显示,需在最后增加以下语句:fp=fopen(filename,”r”);if (fp==NULL) exit(0);while(!feof(fp)){ ch=fgetc(fp); putchar(ch);}fclose(fp);

注:也可用 fflush(stdin)清除 scanf 留下的回车符。

再看例:教材 P230 例 8.1 。

课件制作:刘达明 023-66834110

Page 15: 第 8 章 文    件

2 、字符串的读写函数 (fgets 和 fputs)

第二节 文件操作的相关函数

15 / 31

(第八章 文 件)

⑴fgets 函数 函数原型: char * fgets(char *string, int n, FILE *fp) 功能:从 fp 所指向的文件中读 n-1 个字符,放到以 string 为起始地址的存储空间 (string 可以是数组名 ) 。若在 n-1 个字符前,遇到回车换行符或文件结束符,则读操作结束。在读入的最多 n-1 个字符后面加一个字符串结束符‘ \0’ 标志,使读出的存放在 string 中字符数组为字符串。 返回值:若操作成功,则返回 string 的首地址。否则出错,返回 NULL 。

⑵fputs 函数 函数原型: int fputs(char *string, FILE *fp) 功能:将 string 所表示的字符串内容 ( 不含最后的‘ \0’) 输出到 fp 所指向的文件中去。 返回值:若操作成功,则返回一个非负数。否则出错,返回 -1(EOF) 。

课件制作:刘达明 023-66834110

Page 16: 第 8 章 文    件

例 8.2 从文件中按行读取字符串。

第二节 文件操作的相关函数

16 / 31

(第八章 文 件)

#include <stdio.h>main(int argc,char *argv[]){ FILE *fp; char w[81]; int lines=0; if (argc!=2) exit(1); if ((fp=fopen(argv[1],”r”))==NULL) { printf(“cannot open file!\n”); exit(0); } while(fgets(w,80,fp)!=NULL) { lines++; puts(w); } printf(“lines=%d\n”,lines); fclose(fp);}

再看: 教材 P232 的例 8.3 。和: 教材 P233 的例 8.4 。

注:这个例子实现的是 DOS 命令中的 type 命令的内容。功能为:显示文本文件。格式: type 文件名

课件制作:刘达明 023-66834110

Page 17: 第 8 章 文    件

3 、数据块读写函数 (fread 和 fwrite)

第二节 文件操作的相关函数

17 / 31

(第八章 文 件)

C语言还提供了用于整块数据的读写函数。可用来读写一组数据,如一个数组元素,一个结构体变量的值等。 ⑴fread 函数 函数原型: int fread(void *buf, int size, int count, FILE *fp) 其中: buf :是一个指针,表示存放读入数据的首地址。 size :表示要读入的数据块的字节数。 count :表示要读入的数据块的块数,即有 count 个 size 字节的数据块 fp :表示文件指针。 功能:从 fp 所指向的文件中读取 count 个 size 字节的数据项,放到由 buf 所指的内存地址中。 返回值:若读取成功,则返回 count 的值,即读取数据项的完整个数。否则出错,返回 -1(EOF) 。

注:①读取成功时,实际读取的数据块可能小于代入的 count 的值。 ② fread 函数通常用于二进制文件的操作。

课件制作:刘达明 023-66834110

Page 18: 第 8 章 文    件

⑵fwrite 函数

第二节 文件操作的相关函数

18 / 31

(第八章 文 件)

函数原型: int fwrite(void *buf, int size, int count, FILE *fp) 其中: buf :是一个指针,表示存放写入数据的首地址。 size :表示要写入的数据块的字节数。 count :表示要写入的数据块的块数,即有 count 个 size 字节的数据块 fp :表示文件指针。 功能:将 buf 所指的内存地址中的 count 个 size 字节的数据项写入 fp 所指向的文件中。 返回值:若写入成功,则返回 count 的值,即写入数据项的完整个数。否则出错,返回 -1(EOF) 。

注:①写入成功时,实际写入的数据块可能小于代入的 count 的值。 ②fwrite 函数通常用于二进制文件的操作。 ③如果文件以二进制形式打开,用 fread 和 fwrite 函数就可以读写任何类型的信息。

课件制作:刘达明 023-66834110

Page 19: 第 8 章 文    件

例 8.3 从磁盘文件 stu_dat 中读数据存入 stu_list 文件中。

第二节 文件操作的相关函数

19 / 31

(第八章 文 件)

#include <stdio.h>#define SIZE 4struct student_type{ char name[10]; int num; int age; char addr[15];}stud[SIZE];void save();void load();main(){ load(); save();}

void save(){ FILE *fp; int i,len; len=sizeof(stuct student_type); if((fp=fopen(“stu_list”,”wb”))==NULL) { printf(“cannot open file!\n”); return; } for(i=0;i<SIZE;i++) if(fwrite(&stud[i],len,1,fp)!=1) printf(“file write error!\n”); fclose(fp);}

课件制作:刘达明 023-66834110

Page 20: 第 8 章 文    件

例 8.3( 续 )

第二节 文件操作的相关函数

20 / 31

(第八章 文 件)

void load(){ FILE *fp; int i,len; len=sizeof(stuct student_type); if((fp=fopen(“stu_dat”,”rb”))==NULL) { printf(“cannot open infile!\n”); return; } for(i=0;i<SIZE;i++) if(fread(&stud[i],len,1,fp)!=1) { if(feof(fp)) { fclose(fp); return; } printf(“file read error!\n”); } fclose(fp);}

如果需要通过键盘输入数据,再存入 stu_dat 文件,则 main 函数改为:

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();}

运行情况:Zhang 1001 19 room_101 ( 回车 )Hu 1002 20 room_102 ( 回车 )Tan 1003 21 room_103 ( 回车 )Ling 1004 21 room_104 ( 回车 )

课件制作:刘达明 023-66834110

Page 21: 第 8 章 文    件

第 8 章 文 件 ----习题 1

21 / 31

《 C 语言程序设计》 龙昭华主编

习 题 ( 一 )

*** 复习本章已讲内容,预习本章剩余内容。

8.1 教材 P243 的习题 8.2 二级考试模拟题中的第⑵小题多选题。

8.2 教材 P247 的习题 8.2 二级考试模拟题中的第⑹小题编写程序中 的第①、②小题。

课件制作:刘达明 023-66834110

Page 22: 第 8 章 文    件

4、格式化读写函数 (fscanf 和 fprintf)

第二节 文件操作的相关函数

22 / 31

(第八章 文 件)

⑴fscanf 函数 函数原型: int fscanf(FILE *fp, char *format, &arg1, …, &argn) 功能:按照 format 给出的控制符格式,把从 fp 所指向的文件中读取的内容,分别赋给变元 arg1,…,argn 。 返回值:若读取成功,则返回已读取数据的个数。若遇文件结束,则返回 -1(EOF) 。若出错,返回 0 。 ⑵fprintf 函数 函数原型: int fprintf(FILE *fp, char *format, arg1, …, argn) 功能:按照 format 给出的控制符格式,将变元 arg1,…,argn 的值写入到 fp 所指向的文件中去。 返回值:若写入成功,则返回实际写入数据的个数。若出错,则返回负数。说明:①格式化读写均采用 ASCII码方式,简单直观,易于理解。②在输入输出时要进行 ASCII码与二进制之间的转换,花费时间,影响速度。③如果文件数据输入输出频繁或文件过大以及对二进制文件不宜采用格式化读写,而应采用数据块读写函数 fread()和 fwrite()。

课件制作:刘达明 023-66834110

Page 23: 第 8 章 文    件

例 8.4 从磁盘文件 vehicle.dat 中读车流量数据存入 vehicle1.dat 文件中。

第二节 文件操作的相关函数

23 / 31

(第八章 文 件)

#include <stdio.h>main(){ FILE *fp1,*fp2; char w[10]; int road1,road2; fp1=fopen(“vehicle.dat”,”r”); fp2=fopen(“vehicle1.dat”,”w”); if(fp1==NULL||fp2==NULL) { printf(“open file error!\n”); exit(0); }else { while(!feof(fp1)) { fscanf(fp1,”%s %d %d”,w, &road1,&road2);

fprintf(fp2,”%s %d %d”, w,road1,road2); } /*end while*/ } /*end if*/}

例子还可参见: 教材 P237 的例 8.7 。

课件制作:刘达明 023-66834110

Page 24: 第 8 章 文    件

5、读写一个字 ( 整数 ) 函数 (putw 和 getw)

第二节 文件操作的相关函数

24 / 31

(第八章 文 件)

如: FILE *fp; putw(10,fp); 的作用是将整数 10 输出到 fp 指向的文件。而FILE *fp; int i; i=getw(fp); 的作用是从磁盘文件读一个整数到内存,赋给整型变量 i 。 ANSIC 并不提供这两个函数,因此有的 C 系统不包括 putw 和 getw 函数这时可用如下函数来实现:

getw 函数定义如下:

int getw(FILE *fp){ char *s; int i; s=(char *)&i; /* 使 s 指向 i 的起始地址 */ s[0]=fgetc(fp); s[1]=fgetc(fp); return(i);}

putw 函数定义如下:

int putw(int i,FILE *fp){ char *s; s=(char *)&i; fputc(s[0],fp); fputc(s[1],fp); return(i);}

s[0] s[1]i

课件制作:刘达明 023-66834110

Page 25: 第 8 章 文    件

四、随机文件的读写

第二节 文件操作的相关函数

25 / 31

(第八章 文 件)

随机文件的读写,是指在对文件进行读写操作时,可以对文件中指定位置的信息进行读写操作。这样就需要对文件进行详细定位。 一般地,随机文件的读写适合于具有固定长度记录的文件。 C 语言提供了一组用于随机读写的定位函数,其函数原型都在 stdio.h 中。采用随机读写文件可以在不破坏其它数据的情况下把数据插入到文件中去,也能在不重写整个文件的情况下更新和删除以前存储的数据。 在结构体类型 FILE中有一个文件定位指针 (unsigned char *curp;),实现随机读写的关键是要按要求移动该位置指针,这称为文件的定位。 1 、文件定位函数 (rewind 、 fseek 和 ftell) ⑴rewind 函数 函数原型: void rewind(FILE *fp) 功能:将 fp 所指向的文件的内部位置指针置于文件开头,并清除文件结束标志和错误标志。 返回值:该函数没有返回值。如: rewind(fp); 表示强制将文件指针指向文件头。

课件制作:刘达明 023-66834110

Page 26: 第 8 章 文    件

⑵fseek 函数

第二节 文件操作的相关函数

26 / 31

(第八章 文 件)

函数原型: int fseek(FILE *fp,long offset,int base)其中: base 为“起始点”,分别用 0 、 1 、 2 代表,其含义与名字如下: 文件开始 SEEK_SET 0 文件当前位置 SEEK_CUR 1 文件末尾 SEEK_END 2 offset 为位移量,是指以“起始点”为基点移动的字节数。当位移量为负数时,表示向文件头方向移动 ( 也称后移 ) 。当位移量为正数时,表示向文件尾方向移动 ( 也称前移 ) 。 功能:改变文件位置指针的位置。 返回值:成功时返回 0;失败时返回 -1(EOF) 。如: fseek(fp,20L,0); 表示将文件指针从文件头向前移动 20 个字节。 fseek(fp,-100L,1); 表示将文件指针从当前位置向后移动 100 个字节。 fseek(fp,-30L,SEEK_END); 表示将文件指针从文件尾向后移动 30 个字节。说明: fseek()函数一般用于二进制文件。因为文本文件要进行字符转换,故往往计算的位置会出现混乱或错误。

课件制作:刘达明 023-66834110

Page 27: 第 8 章 文    件

⑶ftell 函数

第二节 文件操作的相关函数

27 / 31

(第八章 文 件)

函数原型: long ftell(FILE *fp) 功能:得到 fp 所指向的文件中的当前位置。该位置用相对于文件头的位移量来表示。 返回值:成功时返回当前读写的位置;失败时返回 -1L(EOF) 。如: long i; FILE *fp; i=ftell(fp);

2 、随机文件的读写函数说明 ①对文件进行定位之后,即在改变文件位置指针之后,即可用前面介绍的任一种读写函数对文件进行随机读写。 ②由于一般是读写一个数据据块,因此常用 fread()和 fwrite()函数随机文件的读写操作。 ③由于定位是否准确的原因,随机文件的操作一般又是对二进制文件进行操作。 ④有的教材对随机文件的操作只介绍了这里的定位函数,还有块数据读写函数。而对前面介绍的除块数据读写函数外的其它函数都认为是顺序文件函数。

课件制作:刘达明 023-66834110

Page 28: 第 8 章 文    件

例 8.5 建立一个可记录 100 个客户的银行帐户 (帐号、姓名、金额 ) 存文件。

第二节 文件操作的相关函数

28 / 31

(第八章 文 件)

#include <stdio.h>struct bankclient{ int count; /* 取值为 1—100*/ char name[10]; float money;};main(){ FILE *fp; int rlen,i,off; struct bankclient client={0,””,0.0}; rlen=sizeof(struct bankclient); fp=fopen(“credit.txt”,”w”); if(fp==NULL) { printf(“open file error!\n”); exit(0); }

for(i=1;i<=100;i++) /*建立 */ fwrite(&client,rlen,1,fp); fclose(fp); fp=fopen(“credit.txt”,”r+”); if(fp==NULL) { printf(“open file error!\n”); exit(1); } /* 以下为修改数据 */ scanf(“%d”,&client.count); getchar(); while(client.count!=0) { gets(client.name); scanf(“%f”,&client.money); getchar(); off=(client.count-1)*rlen;

课件制作:刘达明 023-66834110

Page 29: 第 8 章 文    件

例 8.5( 续 )

第二节 文件操作的相关函数

29 / 31

(第八章 文 件)

fseek(fp,off,0) ; fwrite(&client,rlen,1,fp); scanf(“%d”,&client.count); getchar(); } /*end while*/ rewind(fp); /* 以下为屏幕输出 */ printf(“---------------------------------------\n”); printf(“%5s%10s%10s\n”,”Account”, “Name”,”balance”); while(!feof(fp)) { fread(&client,rlen,1,fp); if(client.count!=0) printf(“%5d%10s%8.2f\n”,client.count, client.name,client.money); } fclose(fp);}

运行情况:34 (enter)DaHai (enter)450.6 (enter)45 (enter)ShanDin (enter)460.8 (enter)67 (enter)BaiLu (enter)890.2 (enter)0 (enter)-------------------------------------Account Name Balance 34 DaHai 450.6 45 ShanDin 460.8 67 BaiLu 890.2

课件制作:刘达明 023-66834110

Page 30: 第 8 章 文    件

例 8.6 把一个浮点数组以二进制方式写入文件 test_b.dat 中。并读出来。

第二节 文件操作的相关函数

30 / 31

(第八章 文 件)

#include <stdio.h> main() { float f[6]={3.2, -4.34, 25.04, 0.1, 50.56, 80.5},t[6];    int i;    FILE *fp; /*创建一个二进制文件只写 */    fp=fopen("test_b.dat", "wb"); /*将 6 个浮点数写入文件中 */    fwrite(f, sizeof(float), 6, fp);   fclose(fp);    fp=fopen("test_b.dat", “rb"); fread(t,sizeof(float),6,fp); for(i=0;i<6;i++) printf(“t[%d]=%5.2f\n”,i,t[i]);}

运行结果:t[0]= 3.20t[1]=-4.34t[2]=25.04t[3]= 0.10t[4]=50.56t[5]=80.50

其它例子: 参见教材 P240 的例 8.8 。

课件制作:刘达明 023-66834110

Page 31: 第 8 章 文    件

第 8 章 文 件 ----习题 2

31 / 31

《 C 语言程序设计》 龙昭华主编

习 题 ( 二 )

*** 复习本章已讲内容。

8.3 教材 P241 的习题 8.1 基本知识题中的第⑴ 至 ⑸小题。

8.4 教材 P242-243 的习题 8.2 二级考试模拟题中的第⑴小题单选题。

8.5 教材 P243 的习题 8.2 二级考试模拟题中的第⑶小题判断题。

8.6 教材 P247 的习题 8.2 二级考试模拟题中的第⑹小题编写程序中 的第③小题。

课件制作:刘达明 023-66834110