第 11章 文件类型第 11章 文件类型
11.1 文件类型与文件指针
11.2 文件的打开与关闭
11.3 文件的读写与建立
11.4 文件辅助操作
11.5 程序设计举例第 11章 文件类型
11.1 文件类型与文件指针
1,文本文件和二进制文件
C语言文件把数据看作是一连串的字符 ( 字节 ) 。
C语言文件是一个字符 ( 字节 ) 的序列,是一字符流或字节流,是一种流式文件 。 根据数据的组织形式,可分为文本文件和二进制文件 。
第 11章 文件类型文本文件又称为 ASCII文件,每一个字节中存放一个 ASCII代码,代表一个字符 。 例如,一个整数 123,
若用 ASCII文件存放,占 3个字节的存储单元,1,2、
3各用一个字节存储 。 而 1,2,3的 ASCII码分别为 49、
50,51,故 123用 ASCII文件存放时,存放形式为
001100010011001000110011。
二进制文件是直接用数据的二进制形式存放 。 例如,对整数 123,二进制为 0000000001111011,用二进制 文 件 存 放,需 2 个 字 节,存 放 形 式 为
0000000001111011。
第 11章 文件类型
2,
在缓冲文件系统中,系统自动在内存中为每个正在使用的文件开辟一个缓冲区,文件的存取都是通过缓冲区进行的 。 缓冲区相当于一个中转站,它的大小由具体的 C版本规定,一般为 512字节 。 缓冲文件系统原来用于处理文本文件 。
在非缓冲文件系统中,系统不为所打开的文件自动开辟缓冲区,缓冲区的开辟由程序完成 。 非缓冲文件系统原来用于处理二进制文件 。
第 11章 文件类型
ANSI C不再采用非缓冲文件系统,而只采用缓冲文件系统,在处理二进制文件时,也通过缓冲文件系统进行 。 ANSI C通过扩充缓冲文件系统,使缓冲文件系统既能处理文本文件,又能处理二进制文件 。
第 11章 文件类型
3,内部文件和外部文件存放在外部介质上的文件称为外部文件,通过文件名标识 。 C程序中的文件称为内部文件,用文件指针来描述 。
程序中要实现对文件的处理,先必须在内部文件与外部文件之间建立联系,打开文件;然后方可对文件进行操作 。 文件最基本的操作是读写操作;操作完成应当切断内部文件与外部文件之间的联系,关闭文件 。
对文件进行的所有操作通过 C编译系统提供的标准函数完成,这些函数的信息包含在头文件,stdio.h”中 。
第 11章 文件类型
11.1.2
文件类型是一特殊的结构体类型,一般命名为
FILE。 用户可以直接使用 FILE来定义文件类型变量,
存放要处理的文件的基本信息 。
各种 C编译系统的 FILE定义可以不同,但均包含进行文件操作所需的各种信息。
第 11章 文件类型下面是 TURBO 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;
第 11章 文件类型
11.1.3 文件指针变量对文件的描述,往往通过指向文件的文件指针变量来进行 。 文件指针变量定义的形式为:
FILE *文件指针变量;
例如,FILE *fp,*fpa[ 10] ;
定义了文件指针变量 fp和文件指针变量数组 fpa。 文件指针变量 fp及文件指针变量数组 fpa的每个分量可以指向一个文件的信息 。
第 11章 文件类型
11.2 文件的打开与关闭
11.2.1 文件的打开文件的打开用 fopen( ) 函数完成,调用方式通常为:
fp=fopen(文件名,文件使用方式);
第 11章 文件类型文件使用方式共有 12 种,用特定字符形成的字符串来描述 。
(1) ″r″方式,以只读方式打开文本文件 。
这时从文件中读数据到内存,故要求文件已经存在 。
用 ″r″方式打开的文件只能读,不能同时写 。
(2) ″w″方式,以只写方式打开文本文件 。
这时将内存中的数据写入到磁盘文件中 。 若文件不存在,建立新文件;若文件存在,则刷新文件,重新建立 。 用 ″w″方式打开的文件只能写,不能同时读 。
第 11章 文件类型
(3) ″a″方式,为文本文件的追加方式 。
用于向已存在的文件尾部追加新的数据,而文件中原来的数据不被破坏 。
(4) ″r+″,″w+″,″a+″方式,打开的文本文件既能读又能同时写 。
″r+″方式,在读的同时可以进行写 。 读写位置指针在头部,若原来存在此文件,则以覆盖方式写 。
″w+″方式,在写的同时可以进行读 。 由于打开文件时,
文件原来的内容被刷新,一般不要在打开文件后立即读文件 。
″a+″:在追加的同时可以进行读 。 读文件时,从文件首部开始;写文件时,在文件尾部追加 。
第 11章 文件类型
(5)″rb″,″wb″,″ab″,″rb+″,″wb+″,″ab+″是使用二进制文件相应的六种方式 。
打开文件可得到三个信息:
① 要访问的文件名 。
② 使用文件的方式 。
③ 哪一个指针变量用于指向被打开的文件 。
打开成功,返回文件指针(文件信息区的起始地址); 不能打开,返回空指针。
第 11章 文件类型例如:
(1) fp=fopen( ″student.dat″,″w″) ;
以只写方式打开当前盘当前目录下的文本文件中的学生数据文件,用户可将数据写入此磁盘文件中 。
(2)fp=fopen( ″c,\cj\cjc.dat″,student.dat″,″r″) ;
以只读方式打开 C盘成绩子目录下 C语言成绩文件,
用户可将文件中数据读出来 。 但此文件必须存在,否则会出错 。
第 11章 文件类型
(3) fp=fopen( ″PRG″,″ab+″) ;
打开二进制文件 PRG,在读的同时也可以写 。
为确保文件的读写操作,对文件是否已正常打开往往加上 if语句进行控制 。 例如:
if( fp=fopen(( ″student.dat″,″w″) ==NULL)
{printf( ″不能打开文件 ! ″) ;
exit( 0) ;
}
第 11章 文件类型说明:
(1) 不是所有编译系统均提供以上 12 种文件使用方式 。
(2) 用 ″r″,″rb″方式打开的文件必须已经存在 。
(3) 用 ″w″,″wb″方式打开的文件,可以存在也可以不存在 。 不存在时,则新建文件;存在时,重新建立,原文件内容不被保留 。
(4) 在读写文本文件时,对回车换行符要进行转换,
读时回车换行符转换成换行符,写时回车换行符转换成回车,换行两个字符 。 对二进制文件,不进行这种转换 。
第 11章 文件类型
(5) 程序运行时,系统自动打开标准输入 stdin、
标准输出 stdout,标准出错输出 stderr三个标准文件 。
stdin,stdout,stderr由系统自动定义,可直接使用 。
(6) 标准设备文件可与普通文件一样操作,但将产生特殊效果 。 如写到打印机,将在程序中实现打印输出控制 。
第 11章 文件类型
11.2.2 文件的关闭文件在使用完后,应及时关闭 。 文件的关闭用
fclose( ) 函数完成,调用方式为:
fclose(文件指针变量);
关闭文件将使文件指针变量与文件名脱钩,即指针变量不再指向该文件 。 文件关闭后不能再用该指针变量对文件进行操作,该指针变量可再指向其它文件 。
顺利执行了关闭操作,将返回函数值 0。如返回一个非 0值,则表示文件关闭出错。
第 11章 文件类型
11.3 文件的读写与建立
11.3.1 字符级数据的读和写
1,字符级数据的读函数原型:
int fgetc ( FILE *fp) ;
功能:从文件指针 fp所指向的文件中读取一个字节的代码值 ( 字符 ),作为函数的返回值 。 正常情况下为一个字符,读到文件尾或出错时为 EOF( -1) 。
第 11章 文件类型说明:
(1) 读完一字节数据后,文件指针自动后移 。
(2) getc和 fgetc是等价的宏 。
(3) 若文件指针为 stdin,则 fgetc( stdin)功能与
getchar( )等价。
第 11章 文件类型
2,字符级数据的写函数原型:
int fputc( int ch,FILE *fp) ;
功能,将 ch写入文件指针 fp所指向的文件中 。 写入成功返回字符值,不成功返回值 EOF。
说明:
(1) 写入数据前,文件指针自动后移 。
(2) puttc和 fputc是等价的宏 。
(3) 若文件指针为 stdout,则 fputc( stdout) 功能与
puttchar( ) 等价 。
(4) 文件的建立通过写操作完成。
第 11章 文件类型
11.3.2 字级数据的读和写
1,字级数据的读函数原型:
int getw( FILE *fp);
功能:
从文件指针 fp所指文件中读一个字的数据 ( 整数 ),并以它作为函数的返回值 。
说明:
非标准 C所提供函数。
第 11章 文件类型
2,字节数据的写函数原型:
int putw( int w,FILE *fp);
功能:
写一个字的数据 ( 整数 ) 到文件指针 fp所指的文件中,并以它作为函数的返回值 。
说明,非标准 C所提供函数。
第 11章 文件类型
11.3.3 字符串级数据的读和写
1,字符串数据的读函数原型:
char *fgets( char *str,int len,FILE *fp) ;
功能:
从文件指针 fp所指的文件中读入一个长度为 len-1的字符串,送入到 str所指内存地址中 。 返回值为 str的首地址,若读到文件尾或出错,则返回值为 NULL。
第 11章 文件类型说明:
(1) 字符串读入后在最后加结尾符 ′\0′。
(2) 将读到的回车符作为字符存储 。 这点与 gets( )
函数不同,gets( ) 把读到的回车符转换成结尾符 。
(3) 字符串数据的读和写亦称,行处理,。
第 11章 文件类型
2.
函数原型:
int fputs (char *str,FILE *fp);
功能:
将 str指针所指字符串写入到文件指针 fp所指文件中 。 若该函数成功调用,返回函数值 0,否则返回函数值非 0。
第 11章 文件类型
11.3.4 数据块数据的读和写
1.
函数原型:
unsigned fread( void *buffer,unsigned size,unsigned
count,FILE *fp) ;
功能:从文件指针 fp所指的文件中读取 count个大小为 size
字节的数据块到 buffer指针所指的内存中 。 读到的数据可能含有各种不同的类型 。 若该函数成功调用,返回 count
的值 。
第 11章 文件类型例如:
int a[ 100] ;
fread( a,2,100,fp) ; /*从 fp读取 100个大小为
2字节的数据块 ( 整数 ) 到数组 a中 */
第 11章 文件类型
2,数据块数据的写函数原型:
unsigned fwrite( void *buffer,unsigned size,unsigned count,
FILE *fp) ;
功能:向文件指针 fp所指的文件写入由 buffer指针所标识的 count个大小为 size字节的数据块 。 若该函数成功调用,返回 count的值 。 例如:
int a[ 100] ;
……
fwrite( a,2,100,fp); /*将整个数组 a写入文件 fp中 */
第 11章 文件类型
11.3.5 格式化数据的读和写函数原型:
int fscanf( FILE *fp,格式字串,变量地址表 ) ;
int fprintf( FILE *fp,格式字串,变量表 ) ;
使用 fscanf( ) 和 fprintf( ) 函数对磁盘文件进行读和写,相当方便 。 但是输入时需将 ASCII码转换为二进制,
输出时需将二进制转换成 ASCII码,需花费较多的时间,
故一般较少采用,而是使用 fread( ) 和 fwrite( ) 函数 。
第 11章 文件类型例如:
int i,j;
float f;
fscanf( fp,″%d%d%f″,&i,&j,&f) ; /*
从 fp中按指定格式读取数据至 i,j,f中 */
第 11章 文件类型
11.3.6 文件的建立步骤对文件操作前必须打开文件,文件打开后才可进行读写操作,操作完成应关闭文件 。
文件的建立步骤如下:
(1) 以写方式打开文件 。
(2) 将数据写入文件,多个数据反复写入 。
(3) 写完数据关闭文件。
第 11章 文件类型例 11-1 定义一个函数,建立存放 26个英文小写字母的文件 LF.DAT。
void creatfile( )
{char l;
FILE *fp;
if(( fp=fopen( ″LF.DAT″,″w″)) ==NULL) /*打开文件 */
{printf( ″不能打开文件 ! ″) ;
exit( 0) ;
}
for( l=′a′; l<=′z′; l++) /*写入数据 */
fputc( l,fp) ;
fclose( fp) ; /*关闭文件 */
}
第 11章 文件类型例 11 - 2 定义一个函数,建立存放某班 50个同学姓名,
C语言成绩的数据文件 CCJ.DAT,原始数据由数组参数传入 。
void creatfile( float x[
{int i;
FILE *fp;
if(( fp=fopen( ″CCJ.DAT″,″wb″)) ==NULL) /*打开文件 */
{printf( ″不能打开文件! ″);
exit( 0);
}
for( i=0; i<=50; i++) /*写入数据 */
fwrite( x+i,4,1,fp);
fclose( fp); /*关闭文件 */
}
第 11章 文件类型写入数据也可以整体一次完成:
fwrite( x,4,50,fp) ;
(1) 文件的建立在操作系统下可通过改向操作完成 。
(2) 数据源文件也可通过任何字处理软件建立 。
(3) 执行一个向打印机写的操作,可在程序中实现数据的打印输出 。
例如:
fp=fopen( ″PRN,″,″w″) ;
fputs( ″HUNAN COMPUTER″,fp ) ; /*打印输出
HUNAN COMPUTER*/
打印输出也可直接使用系统提供的打印机文件指针 stdprn。
第 11章 文件类型
11.3.7 文件的读取控制
while ( fgetc( fp) ! [KG-*4]=EOF)
{读取数据 }
while( ! feof( fp))
{读取数据 }
对于二进制文件,由于最后一个数据可能为 -1
( EOF),最好用 feof( )函数判断。
第 11章 文件类型例 11 - 3 从上例建立的文件 CCJ.DAT中读出学生的 C
语言成绩,求出每个学生与平均成绩之差 。
/*程序 11 - 3,求每个学生与平均成绩之差 */
struct st
{char *name;
float cj;
} C[ 200];
main(
{int i=0,n;
float sum=0,av;
float sav[ 200];
FILE *fp;
第 11章 文件类型
if(( fp=fopen( ″CCJ.EAT″,″rb″)) ==NULL) /*打开文件 */
{printf( ″不能打开文件! ″);
while(! feof( fp)) /*读数据,同时进行累加 */
{fread( c+i,4,1,fp);
sum+=c[ i],cj;
i++;
}
n=i;
av=sum/n; /*求平均成绩 */
for( i=0; i<n; i++) /*求与平均成绩之差并输出 */
{sav[ i] =c[ i],cj-av;
printf( ″%s,%6.1f,%6.1f\n″,c[ i],name,c[ i],cj,sav[ i]);
}
第 11章 文件类型
11.4 文件辅助操作
1.
函数原型:
void rewind ( FILE *fp) ;
功能,使文件的读写位置指针返回文件开头。
第 11章 文件类型
2,随机定位函数函数原型:
int fseek ( FILE *fp,long int numbytes,int origin) ;
功能,将文件的位置指针移动 numbytes个字节,
numbytes为正数表示后移,为负数表示前移 。 其中移动的开始位置由 origin确定,origin的值可以为 0,1,2,或
SEEK -SET,SEEK-CUR,SEEK -END,分别代表
,文件开头,,,当前位置,,,文件末尾,三个特殊位置 。
第 11章 文件类型例如:
(1) fseek ( fp,100l,0) ; /*将文件的位置指针移动到离文件开头 100个字节处 */
(2) fseek ( fp,50l,1) ; /*将文件的位置指针向前移动 50个字节处 */
(3) fseek ( fp,-10l,2) ; /*将文件的位置指针向后移 10个字节处 */利用随机定位函数实现对文件的随机读写 。
第 11章 文件类型
3.
函数原型:
long int ftell( FILE *fp) ;
功能:
得到文件的当前读写位置指针,用相对于文件开头的位移量来表示 。 若出现调用错误,返回值为 -1。
第 11章 文件类型
4,出错检测函数函数原型:
int ferror ( FILE *fp) ;
功能:
检查文件中各种输入输出函数调用是否出错 。
若得到的函数值为 0,表示未出错;得到的函数值非
0,表示出错 。
调用 fopen( )函数时,ferror初值自动置 0。
第 11章 文件类型
5,初始化清零函数函数原型:
void clearerr( FILE *fp) ;
功能:
清除文件错误标志和文件结束,将文件错误标志和文件结束标志置 0。
输入输出函数调用出错后,出错标志一直保留,直到对同一文件调用 clearerr( ) 函数,rewind( ) 函数或任一输入输出函数 。
第 11章 文件类型
11.5 程序设计举例例 11 - 4 从键盘输入若干字符,存入某磁盘文件中,
然后从文件中读取数据打印输出 。
/* 程序 11 - 4,输入若干字符至文件,并打印输出 */
main(
{char ch,*fname;
FILE *fp,*pp;
scanf( ″%s″,fname); /*输入磁盘文件名 */
/*建立文件 */
第 11章 文件类型
if(( fp=fopen( fname,″w″)) ==NULL
{printf( ″文件不能打开! ″);
exit( 0);
}
ch=getchar( );
while( ch! =′\n′
{fputc( ch,fp);
ch=getchar( );
}
fclose( fp);
/*从刚建立的磁盘文件中读取数据,打印输出 */
if(( fp=fopen( fname,″r″)) ==NULL
{printf( ″数据文件不能打开! ″);
exit( 0);
}
第 11章 文件类型
if(( pp=fopen( ″PRN,″,″w″)) ==NULL
{printf( ″打印机没能连接! ″);
exit( 0);
}
ch=fgetc( fp);
while (! feof( fp
{fprintf ( pp,″%6c″,ch);
ch= fgetc( fp);
}
fclose( fp);
fclose( pp);
}
第 11章 文件类型例 11 - 5 学生信息包含有学号,姓名,年龄,成绩及住址,从键盘输入 n个学生的这些信息,然后存入一个磁盘文件 STUDENT.DAT中 。
/*程序 11 - 5,建立学生信息文件 */
# define SIZE 200
struct student
{int num;
char *name;
int age;
float score;
char *addr;
} stud [ SIZE];
int n;
第 11章 文件类型
void save ( ) /*建立文件 STUDENT.DAT*/
{FILE *fp;
int i;
if(( fp=fopen( ″STUDENT.DAT″,″wb″)) ==NULL
{printf( ″不能建立文件! ″);
exit( 0);
}
for ( i=0; i<n; i++
if ( fwrite( &stud[ i],sizeof( struct student),1,fp)! =1
{printf ( ″文件不能写 ! \n″);
exit ( 0);
}
第 11章 文件类型
fclose( fp);
}
main (
{int i;
scanf( ″%d″,&n);
for ( i=0; i<n; i++) /*从键盘输入数据 */
scanf( ″%d%s%d%f%s″,&stud [ i],mum,stud [ i],name,
&stud [ i],age,&stud [ i],score,stud [ i],addr);
save( ); /*调用函数建立文件 */
}
第 11章 文件类型例 11 - 6 编写类似 DOS拷贝命令的文件复制程序。
/* 程序 11 - 6,拷贝命令程序 */
main( int argc,char *argv[
{int i;
FILE *fps,*fpt;
if( argc! =3
{puts( ″命令行参数格式是,执行文件名 源文件名 目标文件名 ″);
exit( 0);
}
if(( fps=fopen( argv[ 1],″rb″)) ==NULL
{printf( ″源文件不能打开! ″);
exit( 0);
}
第 11章 文件类型
if(( fpt=fopen( argv[ 2],″wb″)) ==NULL
{printf( ″目标文件不能建立! ″);
exit( 0);
}
while(! feof( fps
{fread( &i,2,1,fps);
fwrite( &i,2,1,fpt);
}
fclsoe( fps);
fclose( fpt);
}
第 11章 文件类型例 11 - 7 对例 11 - 5建立的磁盘文件 STUDENT.DAT,
首先在屏幕上输出文件内容,然后使指针移到开头,实现文件的复制 。
/*程序 11 - 7,文件的输出复制操作 */
# define SIZE 200
struct student
{int num;
char *name;
int age;
float score;
char *addr;
} stud;
第 11章 文件类型
main(
{FILE *fp1,*fp2;
char *tname;
int i=0;
if(( fp1=fopen( ″STUDENT.DAT″,″rb″)) ==NULL
{printf( ″不能打开文件! ″);
exit( 0);
}
while(! feof( fp1)) /*屏幕输出 */
{fread( &stud,sizeof( struct student),1,fp1
printf( ″%6d%16s%8d%8.1f%28s\n″,stud,mum,stud.name,
stud,age,stud.score,stud.addr);
}
第 11章 文件类型
puts( ″请输入目标文件名 ″);
gets( tname);
rewind( fp1);
if(( fp2=fopen( tname,″wb″)) ==NULL
{printf( ″不能建立文件! ″);
exit( 0);
}
while(! feof( fp1)) /*复制文件 */
{fread( &stud,sizeof( struct student),1,fp1);
fwrite( &stud,sizeof( struct student),1,fp2);
}
fclose( fp1);
fclose( fp2);
}
第 11章 文件类型例 11 - 8 某书店库存数据存于库存文件 BK中,每天的销售数据存于销售文件 BX中 。 编写程序,根据当天的销售数据调整库存文件 。
用一临时文件 BT先保存调整后的库存 。 将库存数据从 BK中读出减去从销售文件 BX中读去的对应销售数据后,写入临时库存文件 BT。 操作完毕,将临时库存文件 BT改名为原库存文件 BK。
第 11章 文件类型
/*程序 11 - 8,文件合并操作 */
struct book
{char *name;
int num;
} ;
main(
{struct book b;
int x;
FILE *fk,*fx,*ft;
if(( fk=fopen( ″BK″,″rb″)) ==NULL
{printf( ″不能打开库存文件! ″);
exit( 0);
}
if(( fx=fopen( ″BX″,″rb″)) ==NULL
{printf( ″不能打开销售文件! ″);
第 11章 文件类型
exit( 0);
}
if(( ft=fopen( ″BT″,″wb″)) ==NULL
{printf( ″不能打开临时库存文件! ″);
exit( 0);
}
while(! feof( fk)) /*进行调整 */
{fread( &b,sizeof( struct book),1,fk);
fread( &x,2,1,fx);
b.num-=x;
fwrite( &b,sizeof( struct book),1,ft);
}
fcloseall( );
system( ″delete BK″); /*删除原库存文件 */
system( ″rename BT BK″); /*将临时库存文件改名为原库存文件名 */
}
11.1 文件类型与文件指针
11.2 文件的打开与关闭
11.3 文件的读写与建立
11.4 文件辅助操作
11.5 程序设计举例第 11章 文件类型
11.1 文件类型与文件指针
1,文本文件和二进制文件
C语言文件把数据看作是一连串的字符 ( 字节 ) 。
C语言文件是一个字符 ( 字节 ) 的序列,是一字符流或字节流,是一种流式文件 。 根据数据的组织形式,可分为文本文件和二进制文件 。
第 11章 文件类型文本文件又称为 ASCII文件,每一个字节中存放一个 ASCII代码,代表一个字符 。 例如,一个整数 123,
若用 ASCII文件存放,占 3个字节的存储单元,1,2、
3各用一个字节存储 。 而 1,2,3的 ASCII码分别为 49、
50,51,故 123用 ASCII文件存放时,存放形式为
001100010011001000110011。
二进制文件是直接用数据的二进制形式存放 。 例如,对整数 123,二进制为 0000000001111011,用二进制 文 件 存 放,需 2 个 字 节,存 放 形 式 为
0000000001111011。
第 11章 文件类型
2,
在缓冲文件系统中,系统自动在内存中为每个正在使用的文件开辟一个缓冲区,文件的存取都是通过缓冲区进行的 。 缓冲区相当于一个中转站,它的大小由具体的 C版本规定,一般为 512字节 。 缓冲文件系统原来用于处理文本文件 。
在非缓冲文件系统中,系统不为所打开的文件自动开辟缓冲区,缓冲区的开辟由程序完成 。 非缓冲文件系统原来用于处理二进制文件 。
第 11章 文件类型
ANSI C不再采用非缓冲文件系统,而只采用缓冲文件系统,在处理二进制文件时,也通过缓冲文件系统进行 。 ANSI C通过扩充缓冲文件系统,使缓冲文件系统既能处理文本文件,又能处理二进制文件 。
第 11章 文件类型
3,内部文件和外部文件存放在外部介质上的文件称为外部文件,通过文件名标识 。 C程序中的文件称为内部文件,用文件指针来描述 。
程序中要实现对文件的处理,先必须在内部文件与外部文件之间建立联系,打开文件;然后方可对文件进行操作 。 文件最基本的操作是读写操作;操作完成应当切断内部文件与外部文件之间的联系,关闭文件 。
对文件进行的所有操作通过 C编译系统提供的标准函数完成,这些函数的信息包含在头文件,stdio.h”中 。
第 11章 文件类型
11.1.2
文件类型是一特殊的结构体类型,一般命名为
FILE。 用户可以直接使用 FILE来定义文件类型变量,
存放要处理的文件的基本信息 。
各种 C编译系统的 FILE定义可以不同,但均包含进行文件操作所需的各种信息。
第 11章 文件类型下面是 TURBO 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;
第 11章 文件类型
11.1.3 文件指针变量对文件的描述,往往通过指向文件的文件指针变量来进行 。 文件指针变量定义的形式为:
FILE *文件指针变量;
例如,FILE *fp,*fpa[ 10] ;
定义了文件指针变量 fp和文件指针变量数组 fpa。 文件指针变量 fp及文件指针变量数组 fpa的每个分量可以指向一个文件的信息 。
第 11章 文件类型
11.2 文件的打开与关闭
11.2.1 文件的打开文件的打开用 fopen( ) 函数完成,调用方式通常为:
fp=fopen(文件名,文件使用方式);
第 11章 文件类型文件使用方式共有 12 种,用特定字符形成的字符串来描述 。
(1) ″r″方式,以只读方式打开文本文件 。
这时从文件中读数据到内存,故要求文件已经存在 。
用 ″r″方式打开的文件只能读,不能同时写 。
(2) ″w″方式,以只写方式打开文本文件 。
这时将内存中的数据写入到磁盘文件中 。 若文件不存在,建立新文件;若文件存在,则刷新文件,重新建立 。 用 ″w″方式打开的文件只能写,不能同时读 。
第 11章 文件类型
(3) ″a″方式,为文本文件的追加方式 。
用于向已存在的文件尾部追加新的数据,而文件中原来的数据不被破坏 。
(4) ″r+″,″w+″,″a+″方式,打开的文本文件既能读又能同时写 。
″r+″方式,在读的同时可以进行写 。 读写位置指针在头部,若原来存在此文件,则以覆盖方式写 。
″w+″方式,在写的同时可以进行读 。 由于打开文件时,
文件原来的内容被刷新,一般不要在打开文件后立即读文件 。
″a+″:在追加的同时可以进行读 。 读文件时,从文件首部开始;写文件时,在文件尾部追加 。
第 11章 文件类型
(5)″rb″,″wb″,″ab″,″rb+″,″wb+″,″ab+″是使用二进制文件相应的六种方式 。
打开文件可得到三个信息:
① 要访问的文件名 。
② 使用文件的方式 。
③ 哪一个指针变量用于指向被打开的文件 。
打开成功,返回文件指针(文件信息区的起始地址); 不能打开,返回空指针。
第 11章 文件类型例如:
(1) fp=fopen( ″student.dat″,″w″) ;
以只写方式打开当前盘当前目录下的文本文件中的学生数据文件,用户可将数据写入此磁盘文件中 。
(2)fp=fopen( ″c,\cj\cjc.dat″,student.dat″,″r″) ;
以只读方式打开 C盘成绩子目录下 C语言成绩文件,
用户可将文件中数据读出来 。 但此文件必须存在,否则会出错 。
第 11章 文件类型
(3) fp=fopen( ″PRG″,″ab+″) ;
打开二进制文件 PRG,在读的同时也可以写 。
为确保文件的读写操作,对文件是否已正常打开往往加上 if语句进行控制 。 例如:
if( fp=fopen(( ″student.dat″,″w″) ==NULL)
{printf( ″不能打开文件 ! ″) ;
exit( 0) ;
}
第 11章 文件类型说明:
(1) 不是所有编译系统均提供以上 12 种文件使用方式 。
(2) 用 ″r″,″rb″方式打开的文件必须已经存在 。
(3) 用 ″w″,″wb″方式打开的文件,可以存在也可以不存在 。 不存在时,则新建文件;存在时,重新建立,原文件内容不被保留 。
(4) 在读写文本文件时,对回车换行符要进行转换,
读时回车换行符转换成换行符,写时回车换行符转换成回车,换行两个字符 。 对二进制文件,不进行这种转换 。
第 11章 文件类型
(5) 程序运行时,系统自动打开标准输入 stdin、
标准输出 stdout,标准出错输出 stderr三个标准文件 。
stdin,stdout,stderr由系统自动定义,可直接使用 。
(6) 标准设备文件可与普通文件一样操作,但将产生特殊效果 。 如写到打印机,将在程序中实现打印输出控制 。
第 11章 文件类型
11.2.2 文件的关闭文件在使用完后,应及时关闭 。 文件的关闭用
fclose( ) 函数完成,调用方式为:
fclose(文件指针变量);
关闭文件将使文件指针变量与文件名脱钩,即指针变量不再指向该文件 。 文件关闭后不能再用该指针变量对文件进行操作,该指针变量可再指向其它文件 。
顺利执行了关闭操作,将返回函数值 0。如返回一个非 0值,则表示文件关闭出错。
第 11章 文件类型
11.3 文件的读写与建立
11.3.1 字符级数据的读和写
1,字符级数据的读函数原型:
int fgetc ( FILE *fp) ;
功能:从文件指针 fp所指向的文件中读取一个字节的代码值 ( 字符 ),作为函数的返回值 。 正常情况下为一个字符,读到文件尾或出错时为 EOF( -1) 。
第 11章 文件类型说明:
(1) 读完一字节数据后,文件指针自动后移 。
(2) getc和 fgetc是等价的宏 。
(3) 若文件指针为 stdin,则 fgetc( stdin)功能与
getchar( )等价。
第 11章 文件类型
2,字符级数据的写函数原型:
int fputc( int ch,FILE *fp) ;
功能,将 ch写入文件指针 fp所指向的文件中 。 写入成功返回字符值,不成功返回值 EOF。
说明:
(1) 写入数据前,文件指针自动后移 。
(2) puttc和 fputc是等价的宏 。
(3) 若文件指针为 stdout,则 fputc( stdout) 功能与
puttchar( ) 等价 。
(4) 文件的建立通过写操作完成。
第 11章 文件类型
11.3.2 字级数据的读和写
1,字级数据的读函数原型:
int getw( FILE *fp);
功能:
从文件指针 fp所指文件中读一个字的数据 ( 整数 ),并以它作为函数的返回值 。
说明:
非标准 C所提供函数。
第 11章 文件类型
2,字节数据的写函数原型:
int putw( int w,FILE *fp);
功能:
写一个字的数据 ( 整数 ) 到文件指针 fp所指的文件中,并以它作为函数的返回值 。
说明,非标准 C所提供函数。
第 11章 文件类型
11.3.3 字符串级数据的读和写
1,字符串数据的读函数原型:
char *fgets( char *str,int len,FILE *fp) ;
功能:
从文件指针 fp所指的文件中读入一个长度为 len-1的字符串,送入到 str所指内存地址中 。 返回值为 str的首地址,若读到文件尾或出错,则返回值为 NULL。
第 11章 文件类型说明:
(1) 字符串读入后在最后加结尾符 ′\0′。
(2) 将读到的回车符作为字符存储 。 这点与 gets( )
函数不同,gets( ) 把读到的回车符转换成结尾符 。
(3) 字符串数据的读和写亦称,行处理,。
第 11章 文件类型
2.
函数原型:
int fputs (char *str,FILE *fp);
功能:
将 str指针所指字符串写入到文件指针 fp所指文件中 。 若该函数成功调用,返回函数值 0,否则返回函数值非 0。
第 11章 文件类型
11.3.4 数据块数据的读和写
1.
函数原型:
unsigned fread( void *buffer,unsigned size,unsigned
count,FILE *fp) ;
功能:从文件指针 fp所指的文件中读取 count个大小为 size
字节的数据块到 buffer指针所指的内存中 。 读到的数据可能含有各种不同的类型 。 若该函数成功调用,返回 count
的值 。
第 11章 文件类型例如:
int a[ 100] ;
fread( a,2,100,fp) ; /*从 fp读取 100个大小为
2字节的数据块 ( 整数 ) 到数组 a中 */
第 11章 文件类型
2,数据块数据的写函数原型:
unsigned fwrite( void *buffer,unsigned size,unsigned count,
FILE *fp) ;
功能:向文件指针 fp所指的文件写入由 buffer指针所标识的 count个大小为 size字节的数据块 。 若该函数成功调用,返回 count的值 。 例如:
int a[ 100] ;
……
fwrite( a,2,100,fp); /*将整个数组 a写入文件 fp中 */
第 11章 文件类型
11.3.5 格式化数据的读和写函数原型:
int fscanf( FILE *fp,格式字串,变量地址表 ) ;
int fprintf( FILE *fp,格式字串,变量表 ) ;
使用 fscanf( ) 和 fprintf( ) 函数对磁盘文件进行读和写,相当方便 。 但是输入时需将 ASCII码转换为二进制,
输出时需将二进制转换成 ASCII码,需花费较多的时间,
故一般较少采用,而是使用 fread( ) 和 fwrite( ) 函数 。
第 11章 文件类型例如:
int i,j;
float f;
fscanf( fp,″%d%d%f″,&i,&j,&f) ; /*
从 fp中按指定格式读取数据至 i,j,f中 */
第 11章 文件类型
11.3.6 文件的建立步骤对文件操作前必须打开文件,文件打开后才可进行读写操作,操作完成应关闭文件 。
文件的建立步骤如下:
(1) 以写方式打开文件 。
(2) 将数据写入文件,多个数据反复写入 。
(3) 写完数据关闭文件。
第 11章 文件类型例 11-1 定义一个函数,建立存放 26个英文小写字母的文件 LF.DAT。
void creatfile( )
{char l;
FILE *fp;
if(( fp=fopen( ″LF.DAT″,″w″)) ==NULL) /*打开文件 */
{printf( ″不能打开文件 ! ″) ;
exit( 0) ;
}
for( l=′a′; l<=′z′; l++) /*写入数据 */
fputc( l,fp) ;
fclose( fp) ; /*关闭文件 */
}
第 11章 文件类型例 11 - 2 定义一个函数,建立存放某班 50个同学姓名,
C语言成绩的数据文件 CCJ.DAT,原始数据由数组参数传入 。
void creatfile( float x[
{int i;
FILE *fp;
if(( fp=fopen( ″CCJ.DAT″,″wb″)) ==NULL) /*打开文件 */
{printf( ″不能打开文件! ″);
exit( 0);
}
for( i=0; i<=50; i++) /*写入数据 */
fwrite( x+i,4,1,fp);
fclose( fp); /*关闭文件 */
}
第 11章 文件类型写入数据也可以整体一次完成:
fwrite( x,4,50,fp) ;
(1) 文件的建立在操作系统下可通过改向操作完成 。
(2) 数据源文件也可通过任何字处理软件建立 。
(3) 执行一个向打印机写的操作,可在程序中实现数据的打印输出 。
例如:
fp=fopen( ″PRN,″,″w″) ;
fputs( ″HUNAN COMPUTER″,fp ) ; /*打印输出
HUNAN COMPUTER*/
打印输出也可直接使用系统提供的打印机文件指针 stdprn。
第 11章 文件类型
11.3.7 文件的读取控制
while ( fgetc( fp) ! [KG-*4]=EOF)
{读取数据 }
while( ! feof( fp))
{读取数据 }
对于二进制文件,由于最后一个数据可能为 -1
( EOF),最好用 feof( )函数判断。
第 11章 文件类型例 11 - 3 从上例建立的文件 CCJ.DAT中读出学生的 C
语言成绩,求出每个学生与平均成绩之差 。
/*程序 11 - 3,求每个学生与平均成绩之差 */
struct st
{char *name;
float cj;
} C[ 200];
main(
{int i=0,n;
float sum=0,av;
float sav[ 200];
FILE *fp;
第 11章 文件类型
if(( fp=fopen( ″CCJ.EAT″,″rb″)) ==NULL) /*打开文件 */
{printf( ″不能打开文件! ″);
while(! feof( fp)) /*读数据,同时进行累加 */
{fread( c+i,4,1,fp);
sum+=c[ i],cj;
i++;
}
n=i;
av=sum/n; /*求平均成绩 */
for( i=0; i<n; i++) /*求与平均成绩之差并输出 */
{sav[ i] =c[ i],cj-av;
printf( ″%s,%6.1f,%6.1f\n″,c[ i],name,c[ i],cj,sav[ i]);
}
第 11章 文件类型
11.4 文件辅助操作
1.
函数原型:
void rewind ( FILE *fp) ;
功能,使文件的读写位置指针返回文件开头。
第 11章 文件类型
2,随机定位函数函数原型:
int fseek ( FILE *fp,long int numbytes,int origin) ;
功能,将文件的位置指针移动 numbytes个字节,
numbytes为正数表示后移,为负数表示前移 。 其中移动的开始位置由 origin确定,origin的值可以为 0,1,2,或
SEEK -SET,SEEK-CUR,SEEK -END,分别代表
,文件开头,,,当前位置,,,文件末尾,三个特殊位置 。
第 11章 文件类型例如:
(1) fseek ( fp,100l,0) ; /*将文件的位置指针移动到离文件开头 100个字节处 */
(2) fseek ( fp,50l,1) ; /*将文件的位置指针向前移动 50个字节处 */
(3) fseek ( fp,-10l,2) ; /*将文件的位置指针向后移 10个字节处 */利用随机定位函数实现对文件的随机读写 。
第 11章 文件类型
3.
函数原型:
long int ftell( FILE *fp) ;
功能:
得到文件的当前读写位置指针,用相对于文件开头的位移量来表示 。 若出现调用错误,返回值为 -1。
第 11章 文件类型
4,出错检测函数函数原型:
int ferror ( FILE *fp) ;
功能:
检查文件中各种输入输出函数调用是否出错 。
若得到的函数值为 0,表示未出错;得到的函数值非
0,表示出错 。
调用 fopen( )函数时,ferror初值自动置 0。
第 11章 文件类型
5,初始化清零函数函数原型:
void clearerr( FILE *fp) ;
功能:
清除文件错误标志和文件结束,将文件错误标志和文件结束标志置 0。
输入输出函数调用出错后,出错标志一直保留,直到对同一文件调用 clearerr( ) 函数,rewind( ) 函数或任一输入输出函数 。
第 11章 文件类型
11.5 程序设计举例例 11 - 4 从键盘输入若干字符,存入某磁盘文件中,
然后从文件中读取数据打印输出 。
/* 程序 11 - 4,输入若干字符至文件,并打印输出 */
main(
{char ch,*fname;
FILE *fp,*pp;
scanf( ″%s″,fname); /*输入磁盘文件名 */
/*建立文件 */
第 11章 文件类型
if(( fp=fopen( fname,″w″)) ==NULL
{printf( ″文件不能打开! ″);
exit( 0);
}
ch=getchar( );
while( ch! =′\n′
{fputc( ch,fp);
ch=getchar( );
}
fclose( fp);
/*从刚建立的磁盘文件中读取数据,打印输出 */
if(( fp=fopen( fname,″r″)) ==NULL
{printf( ″数据文件不能打开! ″);
exit( 0);
}
第 11章 文件类型
if(( pp=fopen( ″PRN,″,″w″)) ==NULL
{printf( ″打印机没能连接! ″);
exit( 0);
}
ch=fgetc( fp);
while (! feof( fp
{fprintf ( pp,″%6c″,ch);
ch= fgetc( fp);
}
fclose( fp);
fclose( pp);
}
第 11章 文件类型例 11 - 5 学生信息包含有学号,姓名,年龄,成绩及住址,从键盘输入 n个学生的这些信息,然后存入一个磁盘文件 STUDENT.DAT中 。
/*程序 11 - 5,建立学生信息文件 */
# define SIZE 200
struct student
{int num;
char *name;
int age;
float score;
char *addr;
} stud [ SIZE];
int n;
第 11章 文件类型
void save ( ) /*建立文件 STUDENT.DAT*/
{FILE *fp;
int i;
if(( fp=fopen( ″STUDENT.DAT″,″wb″)) ==NULL
{printf( ″不能建立文件! ″);
exit( 0);
}
for ( i=0; i<n; i++
if ( fwrite( &stud[ i],sizeof( struct student),1,fp)! =1
{printf ( ″文件不能写 ! \n″);
exit ( 0);
}
第 11章 文件类型
fclose( fp);
}
main (
{int i;
scanf( ″%d″,&n);
for ( i=0; i<n; i++) /*从键盘输入数据 */
scanf( ″%d%s%d%f%s″,&stud [ i],mum,stud [ i],name,
&stud [ i],age,&stud [ i],score,stud [ i],addr);
save( ); /*调用函数建立文件 */
}
第 11章 文件类型例 11 - 6 编写类似 DOS拷贝命令的文件复制程序。
/* 程序 11 - 6,拷贝命令程序 */
main( int argc,char *argv[
{int i;
FILE *fps,*fpt;
if( argc! =3
{puts( ″命令行参数格式是,执行文件名 源文件名 目标文件名 ″);
exit( 0);
}
if(( fps=fopen( argv[ 1],″rb″)) ==NULL
{printf( ″源文件不能打开! ″);
exit( 0);
}
第 11章 文件类型
if(( fpt=fopen( argv[ 2],″wb″)) ==NULL
{printf( ″目标文件不能建立! ″);
exit( 0);
}
while(! feof( fps
{fread( &i,2,1,fps);
fwrite( &i,2,1,fpt);
}
fclsoe( fps);
fclose( fpt);
}
第 11章 文件类型例 11 - 7 对例 11 - 5建立的磁盘文件 STUDENT.DAT,
首先在屏幕上输出文件内容,然后使指针移到开头,实现文件的复制 。
/*程序 11 - 7,文件的输出复制操作 */
# define SIZE 200
struct student
{int num;
char *name;
int age;
float score;
char *addr;
} stud;
第 11章 文件类型
main(
{FILE *fp1,*fp2;
char *tname;
int i=0;
if(( fp1=fopen( ″STUDENT.DAT″,″rb″)) ==NULL
{printf( ″不能打开文件! ″);
exit( 0);
}
while(! feof( fp1)) /*屏幕输出 */
{fread( &stud,sizeof( struct student),1,fp1
printf( ″%6d%16s%8d%8.1f%28s\n″,stud,mum,stud.name,
stud,age,stud.score,stud.addr);
}
第 11章 文件类型
puts( ″请输入目标文件名 ″);
gets( tname);
rewind( fp1);
if(( fp2=fopen( tname,″wb″)) ==NULL
{printf( ″不能建立文件! ″);
exit( 0);
}
while(! feof( fp1)) /*复制文件 */
{fread( &stud,sizeof( struct student),1,fp1);
fwrite( &stud,sizeof( struct student),1,fp2);
}
fclose( fp1);
fclose( fp2);
}
第 11章 文件类型例 11 - 8 某书店库存数据存于库存文件 BK中,每天的销售数据存于销售文件 BX中 。 编写程序,根据当天的销售数据调整库存文件 。
用一临时文件 BT先保存调整后的库存 。 将库存数据从 BK中读出减去从销售文件 BX中读去的对应销售数据后,写入临时库存文件 BT。 操作完毕,将临时库存文件 BT改名为原库存文件 BK。
第 11章 文件类型
/*程序 11 - 8,文件合并操作 */
struct book
{char *name;
int num;
} ;
main(
{struct book b;
int x;
FILE *fk,*fx,*ft;
if(( fk=fopen( ″BK″,″rb″)) ==NULL
{printf( ″不能打开库存文件! ″);
exit( 0);
}
if(( fx=fopen( ″BX″,″rb″)) ==NULL
{printf( ″不能打开销售文件! ″);
第 11章 文件类型
exit( 0);
}
if(( ft=fopen( ″BT″,″wb″)) ==NULL
{printf( ″不能打开临时库存文件! ″);
exit( 0);
}
while(! feof( fk)) /*进行调整 */
{fread( &b,sizeof( struct book),1,fk);
fread( &x,2,1,fx);
b.num-=x;
fwrite( &b,sizeof( struct book),1,ft);
}
fcloseall( );
system( ″delete BK″); /*删除原库存文件 */
system( ″rename BT BK″); /*将临时库存文件改名为原库存文件名 */
}