第 10章 文件第 10章 文件
10.1 文件的概述
10.2文件类型及文件变量的定义
10.3文件 操作
10.4文件的读写
10.5文件的定位
10.6文件应用举例第 10章 文件
10.1 文件的概念
10.1.1 变量的地址与变量的内容文件就是指存储在外存储介质 ( 如磁盘 ) 上的逻辑上具有完整意义的数据集合,每个文件都用一个名字 ( 称为文件名 ) 作标识,通过文件名来达到对数据存取的目的,即所谓,按名称取,。
第 10章 文件
10.2 文件类型及文件变量的定义
1,文件类型计算机的文件类型有很多,本章我们仅讨论通过 C程序的输入输出操作所涉及的,存储在磁盘上的文件 。 对文件可按各种方法进行分类,本章将按以下两种分类方法,一是按文件中数据格式分类,二是按文件读写方式分类 。
第 10章 文件
(1) 按数据格式分类所谓文本文件就是指,当输出时,数据按面值转换成一串字符,
每个字符以字符的 ASCII代码存储到文件中,一个字符占一个字节 。
一个单精度型数据 -12.34在内存中占四个字节,当把它以字符代码的形式存储到文件中时,系统将把它转换成 -,1,2,.(点号 ),3、
4六个字符的 ASCII码并把这些代码依次存入文件中,在文件中占六个字节。
第 10章 文件对于一个字符型数据,占一个字节;对于
int型数据,每个数据占两个字节,其他依次类推。当对二进制文件进行输入输出操作,不必经过任何转换,可直接将数据输入输出,从而提高文件操作速度。
注意,不能将二进制数据直接输出到终端屏幕,也不能从键盘输入二进制数据。
第 10章 文件
( 2) 按读写方式分类
a,顺序文件:读写必须从文件头开始,读取顺序文件中的数据时,从第一个数据读取,直到读取的数据要处理的数据为止 。 如果要把处理后的第 n个数据写回顺序文件中,先要写前 n-1个数据 。
b,随机文件:读写的过程是随机的 。 只要将当前文件中的读写位置设置好,则可对这个数据进行读写操作 。
第 10章 文件
2,文件型指针文件型指针,实际上是指向一个结构体类型的指针变量,这个结构体中包含有诸如:缓冲区的地址,在缓冲区中当前存取的字符的位置,对文件是,读,还是
,写,,是否出错,是否已经遇到文件结束标志等信息 。
对于这个结构型类型,系统已经在名为,stdio.h”头文件中定义好了 。
第 10章 文件其格式如下:
typedef struct
{ int _fd; /*文件代号 */
int _cleft; /*缓冲区中剩下的字符 */
int _mode; /*文件操作模式 */
char *_nextc; /*下一个字符位置 */
char *_buff; /*文件缓冲区位置 */
}FILE;
第 10章 文件定义文件型指针变量的一般形式为:
FILE *文件型指针变量名例如:
FILE *fp;
其中,fp是一个指向 FILE类型结构体的指针变量 。
我们可以使 fp指向某一个文件的结构体变量,从而通过该结构体变量中的文件信息能够访问到该文件 。 也就是说,通过文件指针变量能够找到与它相关的文件并访问这个文件 。
第 10章 文件前面已介绍的三种标准设备文件,系统启动后会自动打开,并且均有一个文件型指针和它们相对应,具体如下:
标准设备文件 文件型指针名标准输入设备 ( 键盘 ) stdin
标准输出设备 ( 显示器 ) stdout
标准错误输出设备 ( 显示器 ) stderr
退出系统时自动关闭这三个标准设备文件 。
第 10章 文件
10.3 文件 操作要对文件进行操作,首先要将其从外存调入内存,
称文件的打开;对文件操作完之后,需要将文件保存到外存,称文件的关闭 。 文件的打开和关闭都是利用系统函数来实现的,它们均包括在名为,stdio.h,的头文件中 。
第 10章 文件
10.3.1 文件的打开调用打开文件函数 fopen函数的一般形式为:
fopen(文件名,文件使用方式 );
通常将 fopen函数的返回值赋予一个文件型指针变量,
例如:
FILE * fp;
fp=fopen( 文件名,文件使用方式 ) ;
fopen函数中这两个参数对应的实参可以是字符中常量,
也可以是字符数组首地址,或者是指向字符串的指针变量 。
第 10章 文件
10.3.2 文件的关闭
fclose函数用来关闭一个由 fopen函数打开的文件,其一般调用格式为:
fclose(文件型指针 );
例如:
fclose(fp);
前面我们曾将 fopen函数的返回值赋予了 fp文件型指针变量,现在通过 fp来关闭该文件 。
fclose函数返回 0,表示文件关闭成功;返回非 0值则表示文件关闭未成功 。 这样我们可以通过函数的返回值来判断文件是否关闭成功 。
第 10章 文件
【 例 10.1】 测试 fopen函数,fclose函数 。
#include "stdio.h"
main( )
{ FILE *fp;
int a;
if(( fp=fopen("HT","w"))==NULL)
{ printf("Can not open this file.\n");
exit(0);
} a=fclose(fp);
if(a==0)
printf("File close succefully");
else
printf("File close error");
}
第 10章 文件
10.4 文件的读写当以合适的方式打开某个文件后,就可以对该文件进行读数据或写数据的操作,这些操作都是通过系统函数来完成的 。 这些函数均包含在头文件,stdio.h”中 。
第 10章 文件
10.4.1 fprintf( )函数和 fscanf( )函数
( 1) fprintf( )函数 。
该函数的调用形式如下:
fprintf(文件指针,格式控制字符串,输出项表 );
功能是将“输出项表”中各项数据按“格式控制字符串”中指定的格式写入到“文件指针”所指向的文件中,返回值为实际输出的字符数。当正确地写入文件若干个数据后,文件内部指针会自动后移到下一个要写数据的位置 。
第 10章 文件例如,如果文件指针 fp已指向了一个已打开的文件,
x,y分别为有初值的整型变量,要将 x,y值写入到 fp所指向的文件中,可用以下语句:
fprintf(fp,"%d,%d",x,y);
注意:为了以后便于读入,两个数之间应当用空格隔开,同时为了以后便于读入,最好不要输出附加的其他字符串 。
第 10章 文件
( 2) fscanf( )函数 。
该函数调用的形式如下:
fscanf(文件指针,格式控制字符串,输入项表 );
功能是从,文件指针,所指的文件中,按照,格式控制字符串,指定的格式,读取多个数据依次放入,输入项表,中所列出的各项中,返回值为已输入的数据个数 。
当正确地读取若干个数据后,文件内部指针自动后移到未读的下一个数据开始位置 。
第 10章 文件例如,如果文件型指针 fp已指向了一个已打开的文件,
x,y分别为整型变量,则以下语句可从 fp所指的文件中读入两个整数放入变量 x,y中:
fscanf(fp,"%d,%d",&x,&y);
注意:文件中的两个整数之间用空格(或回车符、跳格符)隔开。
第 10章 文件
10.4.2 fputc( )函数和 fgetc( )函数
fputc函数和 fgetc函数称为字符输入输出函数,读写的数据是以一个字符为单位 。
( 1) fputc( )函数 。
fputc函数把一个字符输出 ( 写 ) 到磁盘文件上,其一般调用格式为:
fputc(ch,fp);
其中,ch为要写入的字符,它可以是一个字符常量,也可以是一个字符变量 。 fp为文件型指针,通过 fopen函数获得的,已指向某个打开的可写文件 。
第 10章 文件该函数的作用是:将 ch中的字符写到 fp所指向的文件的当前位置 。 如果写入成功,函数返回值为刚写到文件中的字符;否则返回值为 EOF( 在 stdio.h头文件中已定义好的符号常量,其值为 -1) 。
当正确地写入一个字符或一个字节的数据后,文件内部指针会自动后移一个字节的位置 。
第 10章 文件
【 例 10.2】 把从键盘输入的字符原样输出到当前路径下名为
,file.txt”文件中,用字符,@”作为键盘输入结束标志 。
#include "stdio.h"
main( )
{ FILE *fp;
char ch;
if(( fp=fopen("file.txt","w"))==NULL)
{ printf("Can not open this file.\n");
exit(0);
}
while(( ch=getchar( ) )!= '@' )
fputc( ch,fp);
fclose( fp );
}
第 10章 文件
( 2) fgetc( )函数 。
fgetc函数从指定文件中读取一个字符,该文件必须是以读或读写方式打开的 。 其一般调用格式为:
ch=fgetc( fp );
其中,fp为文件型指针变量,通过 fopen函数获得的已指向某个打开的可读文件,ch为字符型变量 。
该函数的作用是:从 fp所指向的文件当前位置读取单个字符带回赋予字符变量 ch。 如果读取成功,则返回刚才读取的单个字符,否则返回 EOF( -1) 。
第 10章 文件通常,在对文件进行读取字符之前,要先判断当前位置是否在文件末尾,如果不在文件末尾,则可以进行读取字符操作,否则不能进行读取字符的操作 。
文件尾测试函数为 feof函数,该函数的一般格式为:
feof( fp )
其中,fp为文件型指针,指向所要测试的文件。如果 fp
指向的文件当前位置在文件末尾,则函数返回值为非 0,
否则返回值为 0。通过该函数的返回值来判断是否在文件尾。
第 10章 文件
【 例 10.3】 将例 10.2中文件内容输出到显示器上 。
#include "stdio.h"
main( )
{ FILE *fp;
char ch;
if(( fp=fopen("file.txt","r"))==NULL)
{ printf("Can not open this file.\n");
exit(0);
}
第 10章 文件
while( !feof( fp))
{ ch=fgetc(fp);
putchar(ch);
}
fclose(fp);
}
前面我们介绍了显示器作为一种设备文件处理,所以例
10.3中的 while语句可以用以下语句来代替:
while( !feof( fp))
fputc( fgetc(fp),stdout);
第 10章 文件
10.4.3 fputs( )函数和 fgets( )函数
fputs函数和 fgets函数称为字符串输入输出函数,处理的文件是文本文件,读写数据时以字符串为单位 。
( 1) fputs( )函数 。
fputs函数能将一个字符串输出 ( 写 ) 到磁盘文件中,其一般调用格式为:
fputs(str,fp);
其中,str为字符型指针,可以是字符串常量,或存放待输出字符串的字符首地址,或指向待输出字符串的指针变量 。
fp为文件型指针,通过 fopen函数获得的已指向某个打开的可写文件 。
第 10章 文件该函数的作用是:将 str指向的一个字符串,舍弃结束标志 ‘ \0’后写入 fp指向的文件中 。 写入成功函数返回值为正整数,否则为 EOF(-1)。
注意,fputs函数在不同的编译系统中返回值有可能不同 。
当 fpus函数使用 stdout作为 fp参数时,即 fputs(str,stdout)与
puts(str)在功能上有所不同,fputs函数舍弃输出字符串末尾的 ‘ \0’字符,而 puts函数把它转换成回车符输出 。
第 10章 文件
【 例 10.4】 用 fputs函数将一个字符串写入磁盘文件
,f.dat”中,并测试该函数的返回值 。
#include "stdio.h"
main( )
{ FILE *fp;
int n;
char ch[100];
gets(ch);
if(( fp=fopen("f.dat","w"))==NULL)
{ printf("Can not open this file.\n");
exit(0);
}
第 10章 文件
n=fputs(ch,fp);
printf("return number=%d\n",n);
fclose(fp);
}
程序运行结果如下:
Nanchang↙
return number=103
第 10章 文件
( 2) fgets( )函数 。
fgets函数能从文件中读取一个指定长度的字符串,
其一般调用格式为:
fgets(str,n,fp);
其中,str为字符型指针,可以是字符数组首地址,
也可以是指向某个内存区域的指针变量。 n为读取字符的个数,可以是整型常量、整型变量或整型表达式。 fp为文件型指针,通过 fopen函数获得的已指向某个要读取字符串的文件。
第 10章 文件该函数的作用是:从 fp指定的文件中读取 n-1个字符,在其后补充一个字符串结束标志‘ \0’,组成字符串并存入
str指定的内存区。如果读取前 n-1个字符时有回车符,则只读取到回车符止(包括该回车符),并在其后加‘ \0’
字符;如果读取前 n-1个字符时遇到文件末尾,则停止读取字符并在所读取到的字符后添加‘ \0’字符。读取字符成功,该函数返回 str对应的地址,否则返回 NULL( 0)。
当 fgets函数使用 stdin作为 fp参数时,即 fgets(str,n,stdin)与
gets(str)在功能上有所不同,fgets函数把读取到的回车符作为字符存储,然后再在末尾追加‘ \0’字符,而 gets函数把读取到的回车符转换成‘ \0’字符。
第 10章 文件
【 例 10.5】 用 fgets函数将例 10.4中 f.dat文件内容输出到显示器上 。
#include "stdio.h"
main( )
{ FILE *fp;
char str[100];
if(( fp=fopen("f.dat","r"))==NULL)
{ printf("Can not open this file.\n");
exit(0);
}
第 10章 文件
fgets(str,100,fp);
puts(str);
fclose(fp);
}
程序运行结果如下:
Nanchang
第 10章 文件
10.4.4 fread( )函数和 fwrite( )函数
fread函数和 fwrite函数用来读写二进制文件 。
( 1) fread( )函数 。
fread函数称读数函数,其一般调用格式如下:
fread(buffer,size,count,fp);
第 10章 文件其中,buffer为指针,表示要存入数据的首地址 。 size
为无符号整型,表示读取的每个数据所占用的字节数,
通常用,sizeof(数据类型符 )”表示 。 count为无符号整型,表示要读取数据的次数 。 fp为文件型指针,指向要读取数据的文件 。
该函数的作用是:在 fp指定的文件中读取 count次数据项 ( 每个数据项占 size个字节 ) 存放到以 buffer所指的内存地址中 。
读取数据成功,该函数返回 count值,否则返回 NULL
( 0) 。
第 10章 文件
【 例 10.6】 设当前路径下有名为,ABC.DAT”的二进制数据文件,现要从中读取 5个整数,输出到显示器上 。
#include "stdio.h"
main( )
{ FILE *fp;
int a[5],k;
if(( fp=fopen("ABC.DAT","rb"))==NULL)
{ printf("Can not open this file.\n");
exit(0);
}
第 10章 文件
fread(a,sizeof(int),5,fp);
for(k=0; k<5; k++)
printf("%d ",*(a+k));
fclose(fp);
}
第 10章 文件
( 2) fwrite( )函数 。
fwrite函数称写数据函数,其一般调用格式为:
fwrite(buffer,size,count,fp);
其中,buffer为指针,表示输出数据在内存中存放的首地址 。 size为无符号整型,表示每次要写入到文件中数据所占用的字节数,通常用,sizeof(数据类型符 )”
表示 。 count为无符号整型,表示要写入文件中数据的次数 。 fp为文件型指针,指向要写入数据的文件 。
第 10章 文件
【 例 10.7】 将 5个学生记录写入一个磁盘文件,fh.dat”
中 。
#define N 5
#include "stdio.h"
typedef struct
{ char name[10];
int score;
}RECORD;
main( )
第 10章 文件
{ FILE *fp;
RECORD student[N];
int k;
if(( fp=fopen("fh.dat","wb"))==NULL)
{ printf("Can not open this file.\n");
exit(0);
}
printf("input:name and score\n");
第 10章 文件
for(k=0; k<N; k++)
{scanf("%s%d",student[k].name,&student[k].score);
fwrite(&student[k],sizeof(RECORD),1,fp);
}
fclose(fp);
}
第 10章 文件
10.5 文件的定位
rewind函数称为文件头定位函数,其一般调用格式为:
rewind(fp);
其中,fp是指向由 fopen函数打开的文件型指针 。
该函数的作用是:使文件内部指针置于 fp所指向的文件开头 。
此函数无返回值 。
10.5.1 rewind( )函数第 10章 文件
【 例 10.8】 设当前路径下有一文件名为,ch1.txt”,先显示,ch1.txt”文件内容,然后再将该文件复制到当前路径下名为,ch2.txt”的文件中 。
#include "stdio.h"
main( )
{ FILE *fp1,*fp2;
if(( fp1=fopen("ch1.txt","r"))==NULL)
{ printf("Can not open this file.\n");
exit(0);
}
第 10章 文件
if(( fp2=fopen("ch2.txt","w"))==NULL)
{ printf("Can not open this file.\n");
exit(0);
}
while( !feof(fp1) )
fputc(fgetc(fp1),stdout);
rewind(fp1);
while( !feof(fp1) )
fputc(fgetc(fp1),fp2);
fclose(fp1);
fclose(fp2);
}
第 10章 文件
10.5.2 fseek( )函数
fseek函数称为文件随机定位函数,对随机文件读写操作时要用到 fseek函数来定位读写位置 。 其一般调用格式为:
fseek(fp,offset,from);
第 10章 文件在 stdio.h头文件中定义如下:
整数 0 1 2
名称 SEEK_SET SEEK_CUR SEEK_END
起始位置 文件开头 文件当前位置 文件末尾第 10章 文件该函数的作用是:将文件位置指针移到由起始位置开始,位移量为 offset的字节处 。 如果成功,则返回当前位置,否则返回 -1。
例如:
fseek(fp,-100L,2); /*表示从文件尾开始前移 100个字节的位置 */
fseek(fp,50L,SEEK_SET); /*表示从文件头开始后移
50个字节的位置 */
本函数一般用于二进制文件,因为文本文件要发生字符转换,计算位置时往往会发生混乱 。
第 10章 文件
【 例 10.9】 设当前路径下有一个名为,stu.dat”的二进制文件,其中连续存放了 20个整数,要求读取并显示其中第 1,3,5个数据 。
#include "stdio.h"
main( )
{ FILE *fp;
int k,f;
if(( fp=fopen("stu.dat","rb"))==NULL)
{ printf("Can not open this file.\n");
exit(0);
}
第 10章 文件
for(k=0; k<3; k++)
{ fseek(fp,(long)(k*sizeof(int)),0); /*指向当前要读取数据的位置 */
fread(&f,sizeof(int),1,fp); /*从当前位置读取一个整数 */
printf("%d,%d\n",2*k+1,f);
}
fclose(fp);
}
第 10章 文件
10.5.3 ftell( )函数
ftell函数用以获得文件当前位置指针的位置,函数给出当前位置指针相对于文件开头的字节数 。 由于文件中的位置指针经常移动,人们往往不容易辨清其当前位置 。 用户要想了解文件位置指针的位置,可用 ftell函数 。
该函数的一般调用格式为:
t=ftell(fp);
其中,t为 long型变量,fp为文件型指针,指向一个已打开的文件 。 当函数调用出错时,函数返回 -1L。
第 10章 文件当打开一个文件时,通常并不知道该文件的长度,
可以通过以下函数调用求出文件长度的字节数:
fseek(fp,0L,SEEK_END); /*位置指针移至文件末尾 */
t=ftell(fp); /*求出文件中的字节数 */
第 10章 文件
10.6 文件应用举例
【 例 10.10】 设当前路径下有一个名为,chang.txt”文件,现要将文件中所有小写字母改写为大写字母后存回原文件中,文件中其他字符不变 。
#include "stdio.h"
#include "stdlib.h"
#include "ctype.h"
main( )
{ FILE *fp;
char ch; if(( fp=fopen("chang.txt","r+"))==NULL)
{ printf(“Can not open this file.\n”); exit(0);
}
第 10章 文件
while(( ch=fgetc(fp))!=EOF)
if(islower(ch)!=0)
{ fseek(fp,-1L,SEEK_CUR); /*将文件位置指针前移一个字节 */
ch=toupper(ch);
fputc (ch,fp);
fseek(fp,0L,SEEK_CUR); /*将文件位置指针重新定位在当前位置 */
}
fclose(fp);
}
第 10章 文件本章小结本章介绍了 C文件的基本概念,C语言对文件的操作是通过调用库函数进行的 。 通过本章学习,要求掌握有关文件操作的库函数的使用方法,能设计对文件进行简单处理的实用程序 。
( 1) 在 C语言中,根据数据的组织方式文件可分为二进制文件和文本文件 。
( 2) 对文件操作,首先要打开,最后要关闭 。 在对文件读写操作时需要依靠文件内部位置指针来完成,文件位置指针是一个形象化概念,它指向文件当前读写位置 。
第 10章 文件
( 3) 对文件型指针变量的定义形式为:
FILE *指针变量名;
其中,FILE为在,stdio.h”文件中定义好的标识符 。
( 4) 在打开文件时,需要指定文件的使用方式,针对文件类型选择不同的打开方式 。
( 5)对 C文件既可以顺序读取,也可以随机读取。