10.1 C
文件的有关知识
10.1.1 什么是文件
在程序设计中,主要用到两种文件:
- 程序文件:包括源程序文件
.c
、目标文件.obj
、可执行文件.exe
等; - 数据文件:文件的内容不是程序,而是供程序运行时读写的数据或在程序运行过程中供读入的数据;
10.1.2 文件名
一个文件有一个唯一的文件标识,以便用户识别和引用,文件识别包括3部分:
- 文件路径
- 文件名主干
- 文件名后缀
文件路径表示文件在外部存储设备中的位置,如:
表示file1.dat
文件存放在D
盘中的CC
目录下的temp
子目录下面,文件标识常被称为文件名,文件名主干的命名规则遵循标识符的命名规则,后缀用来表示文件的性质,如:
doc
:word
生成的文件;txt
:文本文件;dat
:数据文件;c
:C
语言源程序文件;cpp
:C
源程序文件;for
:FORTRAN
语言源程序文件;pas
:Pascal
语言源程序文件;obj
:目标文件;exe
:可执行文件;ppt
:电子幻灯片;bmp
:图形文件;
10.1.3 文件的分类
根据数据的组织形式,数据文件可分为ASCII
文件和二进制文件,数据在内存中是以二进制形式存储的,如果不加转换的输出到外存,就是二进制文件,可以认为它就是存储在内存的数据的映像,即映像文件;如果要求在外存上以ASCII
代码形式存储,则需要在存储前进行转换,ASCII
文件又称文本文件,每一个字节存放一个字符的ASCII
代码。
一个数据在磁盘上怎样存储呢?字符一律以ASCII
形式存储,数值型数据既可以用ASCII
形式存储,也可以用二进制形式存储。
10.1.4 文件缓冲区
所谓缓冲文件系统是指系统自动地在内存区为程序中每一个正在使用的文件开辟一个文件缓冲区,从内存向磁盘输出数据必须先送到内存中的缓冲区,装满缓冲区后才一起送到磁盘去,如果从磁盘向计算机读入数据,则一次从磁盘文件将一批数据输入到内存缓冲区,然后在从缓冲区逐个地将数据送到程序数据区,缓冲区的大小由各个具体的C
编译系统确定。
10.1.5 文件类型指针
每个被使用的文件都在内存中开辟一个相应的文件信息区,用来存放文件的有关信息,如文件的名字、文件状态以及文件当前位置等,如FILE *fp
所示即为定义fp
是一个指向FILE
类型数据的指针变量,可以使fp
指向某一个文件的文件信息区,通过该文件信息区中的信息就能够访问该文件,也就是说,通过文件指针变量能够找到与它关联的文件。
指向文件的指针变量并不是指向外部介质上的数据文件的开头,而是指向内存中的文件信息区的开头。
10.2 打开与关闭文件
所谓打开是指为文件建立相应的信息区(用来存放有关文件的信息 )和文件缓冲区(用来暂时存放输入输出的数据),在打开文件的同时,一般都指定一个指针变量指向该文件,也就是建立起指针变量与文件之间的联系,这样就可以通过该指针变量对文件进行读写了,所谓关闭是指撤销文件信息区和文件缓冲区,使文件指针变量不再指向该文件,显然就无法进行对文件的读写了。
10.2.1 用fopen
函数打开数据
例10.1 文件的打开与关闭
代码语言:javascript复制#include <stdio.h>
#include<stdlib.h>
#include<time.h>
int main(){
FILE *input ,*destfile;
int t;
input = fopen("1.txt","r");
destfile = fopen("2.txt" , "w");
if(input == NULL){
// 抛出最近一次的系统错误信息
perror("the file is empity");
exit(EXIT_FAILURE);
}
else{
perror("the file is not empity");
// feof()函数用来检测当前流文件上的文件结束表识,判断是否读到了文件结尾。
while(!feof(input)){
t = fgetc(input);
if(t =='{'){
t ='s';
}
printf("%c" , t);
fputc(t , destfile);
}
}
// 用于清空文件缓冲区
fflush(stdout);
fclose(destfile);
fclose(input);
return 0;
}
fopen
函数的调用方式为:fopen(文件名,使用文件方式)
程序中可以使用3个标准的流文件 — 标准输入流stdin
、标准输出流stdout
、标准出错输出流stderr
,系统已对这3个文件指定了与终端的对应关系,标准输入流是从终端的输入,标准输出流是向终端的输出,标准出错输出流是当程序出错时将出错信息发送到终端。
程序开始运行时系统自动打开这3个标准流文件,因此,程序编写者不需要在程序中用fopen
函数打开它们。所以我们以前用到的从终端输入或输出到终端都不需要打开终端文件,系统定义了3个文件指针变量stdin
、stdout
、stderr
,分别指向标准输入流、标准输出流和标准出错输出流,可以通过这3个指针变量对以上3种流进行操作,它们都以终端作为输入输出对象,如果程序中指定要从stdin
所指的文件输入数据,就是指从终端键盘输入数据。
10.2.2 用fclose
函数关闭数据文件
fclose
函数调用的一般形式为:fclose(文件指针)
在使用完一个文件后应该关闭它,以防止它再被误用,关闭就是撤销文件信息区和文件缓冲区,使文件指针变量不再指向该文件,也就是文件指针变量与文件脱钩,此后不能再通过该指针对原来与其相联系的文件进行读写操作,除非再次打开,使该指针变量重新指向该文件。
如果不关闭文件将会丢失数据。因为,在向文件写数据时,是先将数据输出到缓冲区,待缓冲区充满后才正式输出给文件。如果当数据未充满缓冲区而程序结束运行,就有可能使缓冲区中的数据丢失。要用fclose
函数关闭文件,先把缓冲区中的数据输出到磁盘文件,然后才撤销文件信息区。有的编译系统在程序结束前会自动先将缓冲区中的数据写到文件,从而避免了这个问题,但还是应当养成在程序终止之前关闭所有文件的习惯。
fclose
函数也带回一个值,当成功地执行了关闭操作,则返回值为0;否则返回EOF(-1)
。
10.3 顺序读写数据文件
10.3.1 怎样向文件读写字符
例10.2 从键盘输入字符,逐个把它们送到磁盘上去,直到用户输入一个#
为止。
#include <stdio.h>
#include<stdlib.h>
int main(){
FILE *fp;
char ch,filename[10];
printf("请输入所用的文件名:");
scanf("%s",filename);
if ((fp = fopen(filename,"w")) == NULL) {
printf("无法打开此文件!n");
exit(0);
}
ch = getchar();
printf("请输入一个字符(以#结束):");
ch = getchar();
while (ch!='#')
{
fputc(ch,fp);
putchar(ch);
ch = getchar();
}
fclose(fp);
putchar(10);
return 0;
}
效果如下所示:
fopen
函数打开成功之后会返回该文件所建立的信息区的起始地址,并将其赋值给指针变量fp
;exit
是标准的C
库函数,其作用是使程序终止,用此函数时在程序的开头应包含stdlib.h
头文件。
例10.3 将file1.dat
的内容复制到file2.data
中。
#include <stdio.h>
#include<stdlib.h>
int main(){
FILE *in,*out;
char ch,infile[10],outfile[10];
printf("请输入读入的文件名:");
scanf("%s",infile);
printf("请输入要写入的文件的名字:");
scanf("%s",outfile);
if ((in = fopen(infile,"r")) == NULL) {
printf("无法打开此文件!n");
exit(0);
}
if((out = fopen(outfile, "w"))==NULL){
printf("无法打开此文件!n");
exit(0);
}
while (!feof(in)) {
ch = fgetc(in);
fputc(ch, out);
putchar(ch);
}
fclose(in);
fclose(out);
putchar(10);
return 0;
}
效果如下所示:
用feof
函数可以检查到文件读写位置标记是否移到文件的末尾,即磁盘文件是否结束,若结束则返回1,否则返回0。
10.3.2 怎样向文件读写一个字符串
「注」:
- 若
fgets
函数执行成功,则返回值为str
数组首元素的地址,如果一开始就遇到文件尾或读数据出错,则返回NULL
; fputs
函数的原型为int fputs(char *str,FILE *fp)
,其作用是将str
所指向的字符串输出到fp
所指向的文件中,该函数第一个参数可以是字符串常量、字符数组名或字符型指针,字符串末尾的