http://bbs.elecfans.com 电子技术论坛 http://www.elecfans.com 电子发烧友第 6章 文 件
§ 6.1 文件概述
§ 6.2 文件类型指针
§ 6.3 文件操作的相关函数
§ 6.4 应用举例
1 / 31
,程序设计基础-C语言,龙昭华主编
http://bbs.elecfans.com 电子技术论坛 http://www.elecfans.com 电子发烧友
§ 6.1 文件概述
(第 6章 文 件)
2 / 31
所谓 的,文件,( file)一般指,存储在外部介质上的相关数据的集合 。存放文件的外部介质有磁带、磁盘、光盘等外部存储器。数据 包括,数字、文字、
图形、图象、声音、视频等。 在本章 所讲的文件是由 数字和文字 组成的数据文件 。
以前各章中所用到的输入输出,都是以屏幕等 (标准输出文件指针,stdout)
为输出设备,以键盘 (标准输入文件指针,stdin)为输入设备。而程序运行有时需要把数据存放到磁盘中,这就要用到磁盘文件。
C语言把文件看作是 一个字符 (字节 )的序列,即由一个一个的字符或字节的数据顺序组成。换句话说,C语言是把每一个文件都看作是一个 有序的字节流 。
一,C文件的概念
0 结束标志n-1n-21 2 3 4 ………
流是文件和程序之间的通道。一个 C程序可以创建文件和对文件内容进行更新、修改,在程序中所需的数据也可以从另一个文件中获得。
对文件的操作一般通过三个步骤完成:打开文件、读或写文件、关闭文件。
http://bbs.elecfans.com 电子技术论坛 http://www.elecfans.com 电子发烧友二,文件系统
3 / 31
在 C语言中,根据操作系统对文件的处理方式的不同,把文件系统分为缓冲文件系统和非缓冲文件系统。 ANSI C标准采用 缓冲文件系统 。
缓冲文件系统 (又称标准 I/O)是指操作系统在内存中为每一个正在使用的文件开辟一个读写缓冲区。 从内存向磁盘输出数据时,必须先送到内存缓冲区,
装满缓冲区后才一起送到磁盘去。如果从向内存读入数据,则一次从磁盘文件将一批数据输入到内存缓冲区,然后再从内存缓冲区逐个地将数据送到程序数据区 (变量 )。
(第 6章 文 件)
文件外存程序数据区输入缓冲区输出缓冲区输入输出 输出 (写 )
输入 (读 )
内 存
§ 6.1 文件概述
http://bbs.elecfans.com 电子技术论坛 http://www.elecfans.com 电子发烧友三,文件分类
4 / 31
(第 6章 文 件)
缓冲文件系统解决了高速 CPU与低速外存之间的矛盾,使用它延长了外存的使用寿命,也提高了系统的整体效率。
非缓冲文件系统 (又称系统 I/O)是 指系统不自动开辟确定大小的内存缓冲区,
而由程序自己为每个文件设定缓冲区。
标准 I/O与系统 I/O分别采用不同的输入输出函数对文件进行操作。由于 ANSI
C只采用缓冲文件系统,因此本章所讲的函数也只是处理标准 I/O的函数。
1、从用户角度分类从用户的角度文件分为 标准设备文件 和 普通磁盘文件 。
⑴ 标准设备文件,是 指与主机相连的各种外部设备,如显示器、打印机、键盘等。在操作系统中,把外部设备也看作是一个文件来进行管理,把它们的输入、输出等同于对磁盘文件的读和写。
标准输入文件指针,stdin。如果指定从 stdin输入数据,就是键盘输入。
标准输出文件指针,stdout。如果指定 stdout输出数据,就是屏幕等输出。
标准错误输出文件指针,stderr。标准错误输出也是从屏幕终端输出。
⑵ 普通磁盘文件,本章所讲的文件主要针对磁盘文件。
§ 6.1 文件概述
http://bbs.elecfans.com 电子技术论坛 http://www.elecfans.com 电子发烧友
2、按文件的编码方式分类
5 / 31
(第 6章 文 件)
从 文件的编码方式看,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)
转换直接
§ 6.1 文件概述
http://bbs.elecfans.com 电子技术论坛 http://www.elecfans.com 电子发烧友一,文件指针
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;
(第 6章 文 件)
§ 6.2 文件类型指针
http://bbs.elecfans.com 电子技术论坛 http://www.elecfans.com 电子发烧友文件指针 (续 ):
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必须大写。
(第 6章 文 件)
§ 6.2 文件类型指针
http://bbs.elecfans.com 电子技术论坛 http://www.elecfans.com 电子发烧友
(第 6章 文 件)
8 / 31
对文件的操作一般步骤包括:打开文件、读或写文件、关闭文件。 在C语言中,文件操作都是由库函数来完成的。这些库函数包含在 stdio.h头文件中。
一,文件的打开与关闭所谓 打开文件,实际上是建立文件的各种有关信息,并使文件指针指向该文件,以便进行其它各种操作。 关闭文件 则 是 断开指针与文件之间的联系,也就禁止再对该文件进行操作。
1、文件的打开 (fopen函数 )
ANSIC规定了标准输入输出函数库,用 fopen()函数来实现打开文件。 fopen
函数的原型为,FILE *fopen(char *filename,char *mode)
其中参数 filename表示一个 文件名,是用双引号括起来的字符串,这个字符串可以是一个合法的带有路径的文件名。参数 mode表示 对文件的操作模式,mode
的值仍需要用双引号括起来,mode的取值及其含义 详见教材 P××× 的表 6.1。
如,FIEL *fp1; fp1=fopen(“test.c”,”r”); 表示 是在当前目录下打开文件
test.c,只允许进行,读,操作,并使 fp指向该文件。
再如,FIEL *fp2; fp2=fopen(“c:\\tt\\test.exe”,”rb”); 表示打开 C盘下
tt目录中的 test.exe文件,是二进制文件,只允许按二进制方式进行读操作。
§ 6.3 文件操作的相关函数
http://bbs.elecfans.com 电子技术论坛 http://www.elecfans.com 电子发烧友文件使用方式及其意义
9 / 31
(第 6章 文 件)
ASCII
文件操作
ASCII
文件操作二进制文件操作二进制文件操作只读只读只写追加只写追加读写读写读写读写读写读写
r
w
a
r+
w+
a+
rb
wb
ab
rb+
wb+
ab+
打开一个已经存在的文本文件打开一个已经存在的二进制文件建立并打开一个文本文件打开或建立一个文本文件,在末尾写入建立并打开一个二进制文件打开或建立一个二进制文件,在末尾写入打开一个已经存在的文本文件打开一个已经存在的二进制文件建立并打开一个文本文件打开或建立一个文本文件,在末尾写入建立并打开一个二进制文件打开或建立一个二进制文件,在末尾写入
§ 6.3 文件操作的相关函数
http://bbs.elecfans.com 电子技术论坛 http://www.elecfans.com 电子发烧友
2、文件的关闭 (fclose函数 )
10 / 31
fcolse函数的原型为,int fclose(FILE *fp)
功能,使文件指针变量与文件,脱钩,,释放文件结构体和文件指针。
(第 6章 文 件)
#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中声明。
§ 6.3 文件操作的相关函数
http://bbs.elecfans.com 电子技术论坛 http://www.elecfans.com 电子发烧友二,文件操作错误检测
11 / 31
(第 6章 文 件)
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。
§ 6.3 文件操作的相关函数
http://bbs.elecfans.com 电子技术论坛 http://www.elecfans.com 电子发烧友三,顺序文件的读写
12 / 31
(第 6章 文 件)
文件的顺序读写,是指文件被打开后,按照数据流的先后顺序对文件进行读写操作。每读写一次后,文件指针自动指向下一个读写位置。
1、单个字符的读写函数 (fgetc和 fputc)
⑴ fgetc函数(与 getc一样)
函数原型,int fgetc(FILE *fp)
功能,从 fp所指向的文件中取得下一个字符。
返回值,若正常,则返回所得到的字符 ASCII码值。否则读到文件尾 (键盘输入时 Ctrl+Z表示文件结尾)或出错,返回 -1(EOF)。
注意,前面讲过的 getchar函数实际上是以下宏定义来实现的:
#define getchar() fgetc(stdin)
说明,① 在 fgetc函数调用中,读取的文件必须是以 读 或 读写 方式打开的。
② 读取字符的结果也可以 不向字符变量赋值,这时 读出的字符 被丢失 。 ③ 在文件 内部有一个位置指针,用来指向文件的当前读写字节。 该指针由 系统自动设置,用户不用关心。每执行一次 fgetc该指针自动下移一个字节,因此 fgetc可用在循环中读取文件的所有字符。
§ 6.3 文件操作的相关函数
http://bbs.elecfans.com 电子技术论坛 http://www.elecfans.com 电子发烧友
⑵ fputc函数(与 putc一样)
13 / 31
(第 6章 文 件)
函数原型,int fputc(int ch,FILE *fp)
功能,把一个字节代码 ch写入 fp所指向的文件中。
返回值,若正常,则返回字符 ch的 ASCII码值。否则出错,返回 -1(EOF)。
注意,前面讲过的 putchar函数实际上是以下宏定义来实现的:
#define putchar(ch) fputc((ch),stdout)
说明,
① 被写入的文件可以用 写,读写,追加 方式打开 。
② 用写或读写方式打开一个已存在的文件时将清除原有的文件内容,写入字符从文件首开始。
③ 如需 要 保留原有文件内容,希望写入的字符从文件末尾开始存放,必须以追加方式打开文件。
④ 被写入的文件若不存在,则 自动 创建该文件。
⑤ 每写入一个字符,文件内部位置指针向后移动一个字节。
§ 6.3 文件操作的相关函数
http://bbs.elecfans.com 电子技术论坛 http://www.elecfans.com 电子发烧友例 1 从键盘输入字符存入文件中,以 #号结束。
14 / 31
(第 6章 文 件)
#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);
再看例,教材 P××× 例 6.1
例 6.2
§ 6.3 文件操作的相关函数
http://bbs.elecfans.com 电子技术论坛 http://www.elecfans.com 电子发烧友 14 / 31
(第 6章 文 件)
§ 6.3 文件操作的相关函数
/*教材例 6.1*/
#include <stdio.h>
void main(int argc,char *argv[])
{ FILE *fp1,*fp2; char ch;
if(argc!=3) /*文件使用说明 */
{ printf("\n\t*************************************\n");
printf("\tConvert html to text file \n");
printf("\tUsage:htmtotxt [htmfile] [txtfile] \n");
printf("\t***************************************\n");
exit(0);
}
if((fp1=fopen(argv[1],"r"))==NULL)
{printf("Cannot open %s\n",argv[1]); exit(0);}
if((fp2=fopen(argv[2],"w"))==NULL)
{printf("Cannot open %s\n",argv[2]); exit(0);}
do{ if(ch==?<?)
{while(ch!=?>?) ch=fgetc(fp1);}
if(ch!=?>?)
{fputc(ch,fp2);}
}while((ch=fgetc(fp1))!=EOF);
fclose(fp1); fclose(fp2);
printf("\n %s--?%s finished ok -----!\n",argv[1],argv[2]);
}
http://bbs.elecfans.com 电子技术论坛 http://www.elecfans.com 电子发烧友 14 / 31
(第 6章 文 件)
§ 6.3 文件操作的相关函数
/*教材例 6.2*/
#include <stdio.h>
main()
{ FILE *fp1,*fp2;char ch;
int flag; /*大小写变换标志 */
if((fp1=fopen("c:\\turboc2\\caic\\file1.c","r"))==NULL)
{printf("Unable to open input file\n"); return 1;}
if((fp2=fopen("file1.dat","w"))==NULL)
{printf("Unable to open output file\n"); return 1;}
printf("enter flag(0---to upper,noze zero---to lower");
scanf("%d",&flag);
if(flag==0) /*小写变大写 */
{while(!feof(fp1))
{ ch=fgetc(fp1);
if(ch>=?a?&&ch<=?z?) ch=ch+?A?-?a?;
fputc(ch,fp2);
}
}
else /*大写变小写 */
{while(!feof(fp1))
{ ch=fgetc(fp1);
if(ch>=?A?&&ch<=?Z?) ch=ch-?A?+?a?;
fputc(ch,fp2);
}
}
fclose(fp1); fclose(fp2);
}
http://bbs.elecfans.com 电子技术论坛 http://www.elecfans.com 电子发烧友
2、字符串的读写函数 (fgets和 fputs)
15 / 31
(第 6章 文 件)
⑴ 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)。
§ 6.3 文件操作的相关函数
http://bbs.elecfans.com 电子技术论坛 http://www.elecfans.com 电子发烧友例 2 从文件中按行读取字符串。
16 / 31
(第 6章 文 件)
#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);
}
再看:
教材 P××× 的例 6.3。
和:
教材 P××× 的例 6.4。
注,
这个例子实现的是 DOS命令中的 type命令的内容。
功能为:显示文本文件。
格式,type 文件名
§ 6.3 文件操作的相关函数
http://bbs.elecfans.com 电子技术论坛 http://www.elecfans.com 电子发烧友
3、数据块读写函数 (fread和 fwrite)
17 / 31
(第 6章 文 件)
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函数通常用于二进制文件的操作。
§ 6.3 文件操作的相关函数
http://bbs.elecfans.com 电子技术论坛 http://www.elecfans.com 电子发烧友
⑵ fwrite函数
18 / 31
(第 6章 文 件)
函数原型,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函数就可以读写任何类型的信息。
§ 6.3 文件操作的相关函数
http://bbs.elecfans.com 电子技术论坛 http://www.elecfans.com 电子发烧友例 3 从磁盘文件 stu_dat中读数据存入 stu_list文件中。
19 / 31
(第 6章 文 件)
#include <stdio.h>
#define SIZE 4
struct 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);
}
§ 6.3 文件操作的相关函数
http://bbs.elecfans.com 电子技术论坛 http://www.elecfans.com 电子发烧友例 3(续 )
20 / 31
(第 6章 文 件)
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 (回车 )
§ 6.3 文件操作的相关函数
http://bbs.elecfans.com 电子技术论坛 http://www.elecfans.com 电子发烧友
4、格式化读写函数 (fscanf和 fprintf)
22 / 31
(第 6章 文 件)
⑴ 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()。
§ 6.3 文件操作的相关函数
http://bbs.elecfans.com 电子技术论坛 http://www.elecfans.com 电子发烧友例 4 从磁盘文件 vehicle.dat中读车流量数据存入 vehicle1.dat文件中。
23 / 31
(第 6章 文 件)
#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*/
}
例子还可参见:
教材 P××× 的例 6.6。
§ 6.3 文件操作的相关函数
http://bbs.elecfans.com 电子技术论坛 http://www.elecfans.com 电子发烧友
5、读写一个字 (整数 )函数 (putw和 getw)
24 / 31
(第 6章 文 件)
如,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
§ 6.3 文件操作的相关函数
http://bbs.elecfans.com 电子技术论坛 http://www.elecfans.com 电子发烧友四,随机文件的读写
25 / 31
(第 6章 文 件)
随机文件的读写,是指在对文件进行读写操作时,可以对文件中指定位置的信息进行读写操作。这样就需要对文件进行详细定位。
一般地,随机文件的读写适合于具有固定长度记录的文件 。
C语言提供了一组用于 随机读写的定位函数,其函数原型都在 stdio.h中。采用随机读写文件可以在不破坏其它数据的情况下把数据 插入 到文件中去,也能在不重写整个文件的情况下 更新 和 删除 以前存储的数据。
在结构体类型 FILE中有一个文件定位指针 (unsigned char *curp;),实现随机读写的关键是要按要求移动该位置指针,这称为 文件的定位 。
1、文件定位函数 (rewind,fseek和 ftell)
⑴ rewind函数函数原型,void rewind(FILE *fp)
功能,将 fp所指向的文件的内部位置指针置于文件开头,并清除文件结束标志和错误标志。
返回值,该函数没有返回值。
如,rewind(fp); 表示强制将文件指针指向文件头。
§ 6.3 文件操作的相关函数
http://bbs.elecfans.com 电子技术论坛 http://www.elecfans.com 电子发烧友
⑵ fseek函数
26 / 31
(第 6章 文 件)
函数原型,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()函数一般用于二进制文件。 因为 文本文件要进行 字符 转换,故往往计算的位置会出现 混乱或 错误。
§ 6.3 文件操作的相关函数
http://bbs.elecfans.com 电子技术论坛 http://www.elecfans.com 电子发烧友
⑶ ftell函数
27 / 31
(第 6章 文 件)
函数原型,long ftell(FILE *fp)
功能,得到 fp所指向的 文件 中的当前 位置 。该位置用相对于文件头的位移量来表示。
返回值,成功时返回 当前读写的位置 ;失败时返回 -1L(EOF)。
如,long i; FILE *fp; i=ftell(fp);
2、随机文件的读写函数说明
① 对文件进行定位之后,即 在改变 文件 位置指针之后,即可用前面介绍的任一种读写函数对文件进行随机读写。
② 由于一般是读写一个数据据块,因此常用 fread()和 fwrite()函数 随机文件的读写操作 。
③ 由于定位是否准确的原因,随机文件的操作一般又是对二进制文件进行操作。
④ 有的教材对随机文件的操作只介绍了这里的定位函数,还有块数据读写函数。而对前面介绍的除块数据读写函数外的其它函数都认为是顺序文件函数。
§ 6.3 文件操作的相关函数
http://bbs.elecfans.com 电子技术论坛 http://www.elecfans.com 电子发烧友例 5 建立一个可记录 100个客户的银行帐户 (帐号、姓名、金额 )存文件。
28 / 31
(第 6章 文 件)
#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;
§ 6.3 文件操作的相关函数
http://bbs.elecfans.com 电子技术论坛 http://www.elecfans.com 电子发烧友例 8.5(续 )
29 / 31
(第 6章 文 件)
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
§ 6.3 文件操作的相关函数
http://bbs.elecfans.com 电子技术论坛 http://www.elecfans.com 电子发烧友例 6 把一个浮点数组以二进制方式写入文件 test_b.dat中。并读出来。
30 / 31
(第 6章 文 件)
#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.20
t[1]=-4.34
t[2]=25.04
t[3]= 0.10
t[4]=50.56
t[5]=80.50
其它例子:
参见 教材 P××× 的例 6.7。
§ 6.3 文件操作的相关函数
http://bbs.elecfans.com 电子技术论坛 http://www.elecfans.com 电子发烧友 30 / 31
(第 6章 文 件)
§ 6.4 文件操应用举例参见 教材 P××× 的例 6.8