第十二章 文件.docx
《第十二章 文件.docx》由会员分享,可在线阅读,更多相关《第十二章 文件.docx(11页珍藏版)》请在冰豆网上搜索。
第十二章文件
第十二章文件
§12.1C文件概述
文件:
一般是指存储在外部介质上(如磁盘等)数据有序的集合,用户通过文件名来存取,由操作系统来管理。
现代操作系统把所有外部设备都认为是文件,以便进行统一的管理。
C语言把文件看作是一个字符(字节)的序列,称为流式文件。
(即为无结构的连续字节序列)。
根据数据的组织形式,文件可以分为ASCII文件和二进制文件。
ASCII文件又称为文本文件,其相应数据是以字符形式存放,每一个字符用一个ASCII字符代码表示,而一个ASCII字符代码用一个字节存放。
二进制文件则是以字节为单位存放数据的二进制代码,它将数据按内存中的形式原样保存在文件之中。
两种文件的区别主要在于对数值的存储方式上,对字符的存储是一样的。
如整数123:
ASCII文件:
占用空间较多,花费转换时间。
二进制文件:
不能直接输出。
C语言有两种对文件的处理方式:
“缓冲文件系统”(高层I/O)和“非缓冲文件系统”(低层I/O)。
ANSI标准只采用“缓冲文件系统”。
我们也只重点介绍“缓冲文件系统”。
§12.2文件类型指针
文件指针:
是一个结构体指针,该结构体类型由系统在“stdio.h”中定义,取名FILE。
文件指针变量的定义:
FILE*fp;
在对文件操作的库函数(函数原型都包含在头文件stdio.h中)中,都使用文件型指针变量,表示指向某一个文件。
§12.3文件的打开和关闭
在对文件读写之前必须先将文件打开;当文件不再被使用时,应尽早关闭它(主要基于两点理由:
节省资源;
防止丢失信息)。
一.文件的打开(fopen()函数)
其通常的使用方式为:
FILE*fp;
fp=fopen(“文件名”,“使用文件方式”);
如:
fp=fopen(“a1”,“r”);
文件的使用方式
文本文件
二进制文件
mode
含义
mode
含义
"r"
只读形式打开一个文本文件
"rb"
只读形式打开一个二进制文件
"w"
只写形式创建一个文本文件
"wb"
只写形式创建一个二进制文件
"a"
追加形式打开一个文本文件
"ab"
追加形式打开一个二进制文件
"r+"
读写形式打开一个文本文件
"rb+"
读写形式打开一个二进制文件
"w+"
读写形式创建一个文本文件
"wb+"
读写形式创建一个二进制文件
"a+"
读写形式打开一个文本文件
"ab+"
读写形式打开一个二进制文件
r:
用于以只读方式打开一个己存在文件,打开后只能从该文件中读取数据;
w:
用于以只写方式创建一个新文件,创建后只能向该文件中写入数据,若文件名指定的文件已存在,它的内容将被删去(刷新);
a:
用于以追加方式打开一个已存在文件,打开后可以在文件尾部添加数据。
说明:
1.fopen()函数的返回值是一个FILE类型的文件指针,若打开文件成功该指针将指向在内存中的FILE型结构体(称为内存打开文件结构);若文件打开失败,它将返回一个空指针NULL(NULL在stdio.h中被定义为零值)。
因此常用如下方法进行打开操作:
if((fp=fopen("myfile","r"))==NULL)
{printf("文件打开失败!
\n");
exit(0);
}
exit()函数的作用:
关闭所有文件,终止正在调用的过程。
2.对文本文件:
输入时,将回车,换行符换行符;
输出时,将换行符回车,换行两个符号。
对二进制文件:
不进行这种转换。
3.系统将自动打开三个标准文件:
标准输入:
stdin(文件指针)
标准输出:
stdout
标准出错:
stderr
二.文件的关闭(fclose()函数)
fclose(fp);
fclose返回值:
成功:
0;不成功:
EOF(值为-1,在“stdio.h”中定义)。
§12.4文件的读写
一.字符输入输出
(1)fgetc和fputc函数(getc和putc函数)
函数原型:
charfgetc(FILE*fp);charfputc(charch,FILE*fp);
功能:
从fp指定的流中读取一个字符,写一个字符到fp指定的流中。
返回值:
操作成功时,两函数均返回被操作的字符,否则均返回EOF。
说明:
用fgetc()读二进制文件时,因-1是正常的数据,因此不能用EOF(-1)来判断文件是否结束,一般用feof()进行文件是否结束的判断:
文件结束检测函数:
feof(文件指针)。
在文件正常结束时返回非0值(真),否则返回0(假)。
函数getc()和putc()是fgetc和fputc两个函数派生出来的宏:
#definegetc(fp)fgetc(fp)
#defineputc(ch,fp)fputc(ch,fp)
它们的功能和调用格式分别与函数fgetc()和fputc()完全一样。
p315例13-1从键盘输入一些字符,逐个把它们送到磁盘上去,直到输入一个“#”为止。
#include“stdio.h”
main()
{FILE*fp;
charch,filename[10];
scanf(“%s”,filename);
if((fp=fopen(filename,"w"))==NULL)
{printf("文件打开出错!
\n");
exit(0);
}
ch=getchar();
while(ch!
=’#’)
{fputc(ch,fp);
ch=getchar();
}
fclose(fp);
}
p316例13-2将一个磁盘文件中的信息复制到另一个磁盘文件中。
(文件名在命令行中给出)
#include"stdio.h"
main(intargc,char*argv[])
{intch;
FILE*in,*out;
if(argc!
=3)
{printf(“参数个数不对!
\n”);
exit(0);
}
if((in=fopen(argv[1],"r"))==NULL)
{
printf("输入文件%s打开出错!
\n",argv[1]);
exit
(1);
}
if((out=fopen(argv[2],"w"))==NULL)
{
printf("输出文件%s打开出错!
\n",argv[2]);
exit
(1);
}
while(!
feof(in))fputc(fgetc(in),out);
/*while((ch=fgetc(in))!
=EOF)fputc(ch,out);*/
fclose(in);
fclose(out);
}
若该程序文件名为tem.c,则可用如下命令行执行:
teminfileoutfile
将以上“r”,“w”改为“rb”,“wb”可用来复制一个二进制文件。
(2)getchar和putchar函数
它们是fgetc和fputc两个函数派生出来的宏:
#definegetchar()getc(stdin)
#defineputchar(ch)putc(ch,stdout)
二.数据块读写函数(fread和fwrite函数)
格式:
fread(buffer,size,count,fp);
fwrite(buffer,size,count,fp);
功能:
fread()函数从fp指向的流中读取count(字段数)个字段,每个字段为size(字段长度)个字符长,并把它们放到指针buffer指向内存单元中;fwrite()函数从指针buffer指向的内存单元中,把count个字段写到fp指向的流中去,每个字段为size个字符长。
返回值:
fread()/fwrite()函数返回实际已读取/写入的字段个数,如果实际的个数少于所要求的(count个),则操作失败。
如:
fread(f,4,2,fp)
若:
structstudent
{charname[10];
intnum;
intage;
charaddr[30];
}stud[40];
用于存放40个学生的数据,则可用如下方法将这40个学生的数据从文件中读出:
for(i=0;i<40;i++)
fread(&stud[i],sizeof(structstudent),1,fp);
或将数组中的数据写入文件中:
for(i=0;i<40;i++)
fwrite(&stud[i],sizeof(structstudent),1,fp);
注意:
fread和fwrite函数一般用于二进制文件的输入输出。
三.格式化输入输出(fprintf和fscanf函数)
fprintf()与fscanf()函数的作用与printf()和scanf()函数相仿,后者专门用于标准输入输出流的操作,而前者主要用于对磁盘文件的格式化读写。
格式:
fprintf(fp,格式字符串,输出表列);
fscanf(fp,格式字符串,输入表列);
功能:
fprintf()函数以格式字符串所指定的格式,将输出表列中的数据项向fp所指定的流中输出。
fscanf()函数以格式字符串所指定的格式,从fp所指定的流中读入数据,赋值给其后的输入表列中的变量。
返回值:
fprintf()返回实际被写的字符个数,若出错则返回一个负数;
fscanf()返回实际被赋值的参数个数,返回EOF值则表示试图去读取超过文件尾端的部分。
如:
fprintf(fp,”%d,%6.2f”,i,t);若i=3,t=4.5
则输出到文件:
3,∪∪4.50
fscanf(fp,”%d,%f”,&i,&t);
则在文件中的数据格式应为:
3,4.5
说明:
1.在文件读写函数中,只有fscanf和fprintf函数的文件指针fp放在第一个参数,其他的函数的fp都是最后一个参数。
2.
用fscanf和fprintf函数对磁盘文件读写,使用方便,容易理解。
但要花费转换时间(输入时:
ASCII二进制,输出时:
二进制ASCII。
)
四。
字符串输入输出(fgets和fputs函数)
格式:
fgets(str,n,fp);
fputs(str,fp);
功能:
fgets()函数以文件指针fp指定的流中读入一个字符串放在str中;
fputs()函数写字符串str到fp指定的流中,字符串末尾的’\0’不输出。
返回值:
fgets()函数返回读入的字符串首地址(即str的首地址),读到文件尾或出错时返回一个空指针(NULL);
fputs()函数在写串成功时返回非负整数,否则返回EOF。
例:
写一个字符串到文件中。
#include"stdio.h"
main()
{FILE*fp;
charstr[]="aaasss123456",filename[10];
scanf("%s",filename);
if((fp=fopen(filename,"w"))==NULL)
{printf("文件打开出错!
\n");
exit(0);
}
fputs(str,fp);
fclose(fp);
}
从文件中读一个字符串。
#include"stdio.h"
main()
{FILE*fp;
charstr[20],filename[10];
scanf("%s",filename);
if((fp=fopen(filename,"r"))==NULL)
{printf("文件打开出错!
\n");
exit(0);
}
fgets(str,10,fp);
puts(str);
fclose(fp);
}
§12.5文件的定位
文件中有一个位置指针,指向当前读写的位置。
如果顺序读写一个文件,每次读写一个字符,则读写完一个字符后,该位置指针自动移动,指向下一个字符位置(顺序读写)。
但可以用如下函数改变指针的位置(随机读写)。
一.rewind函数
格式:
rewind(fp);
功能:
rewind()函数将文件指针移到fp所指定的文件的起始位置。
返回值:
成功时返回0,否则返回非零值。
p323例13-4有一个磁盘文件,第一次将它的内容显示在屏幕上,第二次把它复制到另一个文件上。
#include"stdio.h"
main()
{FILE*fp1,*fp2;
if((fp1=fopen("file1.c","r"))==NULL)
{printf("文件1打开出错!
\n");
exit(0);
}
if((fp2=fopen("file2.c","w"))==NULL)
{printf("文件2打开出错!
\n");
exit(0);
}
while(!
feof(fp1))putchar(getc(fp1));
rewind(fp1);
while(!
feof(fp1))putc(getc(fp1),fp2);
fclose(fp1);fclose(fp2);
}
二.fseek函数
格式:
fseek(fp,offset,origin);
功能:
将fp指向的文件的文件指针移动到由起点(origin指定)偏移offset(一般要求是long型数据)个字节的位置处。
返回值:
正确执行时返回0,否则为非零值。
origin指定的起点是下面几个宏之一:
origin(起点)
宏名字
常量值
文件开头
SEEK_SET
0
当前位置
SEEK_CUR
1
文件尾端
SEEK_END
2
这些宏在头文件stdio.h中被定义为整型常量,SEEK_SET为0,代表文件开头位置;SEEK_CUR为1,代表当前位置;SEEK_END为2,代表文件尾端位置。
偏移量n被定义为长整型,实参为常量时书写应用nL表示,其值表示移动的字节数,即相对于origin指定的起点位置的字节数目。
由于使用文本流读写文件时存在某些字符的翻译转换,如流中的单个字符'\n'对应文件中的回车换行两个字符,故在使用fseek()函数时建议用二进制流打开文件,避免应用文本流而可能造成的位置错误。
如:
fseek(fp,100L,0)将文件位置指针移到离文件头向下100个字节处。
fseek(fp,50L,1)将文件位置指针移到离当前位置向下50个字节处。
fseek(fp,-10L,2)将文件位置指针移到离文件尾向上10个字节处。
三.ftell函数
格式:
ftell(fp);
功能:
指出文件指针的当前位置。
返回值:
成功时返回文件指针相对于文件起点的位移的长整型字节数,失败时返回-1L。
可以利用ftell()函数来记录当前文件指针的位置,以备它用。
§12.6出错的检测
一.ferror函数
在调用各种文件输入输出函数(如putc,getc,fread,fwrite等)时,如果出现了错误,除了函数返回值有所反映外,我们还可以使用ferror()函数来进行检查。
格式:
ferror(fp);
功能:
检测fp指定的流中的文件错误。
返回值:
返回值为0时,表示没有出现错误;而非零值表示有错。
在执行fopen()函数时,ferror函数的初值自动置为0。
二.clearerr函数
格式:
clearerr(fp);
功能:
它把fp指向的文件出错标记(ferror(fp)的值)重新置为0,同时文件的结束指示器(feof(fp)的值)也被置为0。