文件类型FILE
文件类型指针(简称文件指针):每个被使用的文件都在内存中开辟一个相应的文件信息区,用来存放文件的有关信息(文件名,文件状态及文件当前位置等)。这些信息是保存在一个结构体变量中的。该结构体类型是由系统声明的,取名为FILE。
例如有一种C编译环境提供的stdio.h头文件中有以下的文件类型声明:
typedef struct
{ short level; //缓冲区“满”或“空”的程度
unsigned flags; //文件状态标志
char fd; //文件描述符
unsigned char hold; //如缓冲区无内容不读取字符
short bsize; //缓冲区大小
unsigned char*buffer; //数据缓冲区的位置
unsigned char*curp; //指针当前的指向
unsigned istemp; //临时文件指示器
short token; //用于有效性检查
}FILE;//FILE等价于结构体
不同C编译系统的FILE类型包含内容不完全相同,但大同小异。
声明FILE的信息在stdio.h中,在程序中可直接用FILE类型名定义变量。
如FILE f1; //定义f1来存放一个文件的有关信息
//这些信息是在打开文件时由系统根据文件的情况自动放入的,用户不必过问
//一般不对FILE类型变量命名,也就是不通过变量的名字来引用这些变量,而是设置一个指向FILE类型变量的指针变量,然后通过它来引用这些FILE类型变量。这样使用起来方便。
FILE *fp; //定义fp是一个指向FILE类型数据的指针变量。
//可以使fp指向某一个文件的文件信息区(是一个结构体变量),通过该文件信息区中的信息就能够访问该文件。即通过文件指针变量能够找到与它关联的文件。若有n个文件,应设n个指针变量,分别指向n个FILE类型变量,以实现对n个文件的访问。
为方便起见,通常将这种指向文件信息区的指针变量简称为指向文件的指针变量。
注意:指向文件的指针变量并不是指向外部介质上的数据文件的开头,而是指向内存中的文件信息区的开头。
打开与关闭文件
对文件读写之前应该“打开”该文件。实际上,所谓“打开”是指为文件建立相应的信息区(用来存放有关文件的信息)和文件缓冲区(用来暂时存放输入输出的数据)。
在编写程序时,在打开文件的同时,一般都指定一个指针变量指向该文件,也就是建立起指针变量与文件之间的联系,这样,就可以通过该指针变量对文件进行读写了。所谓“关闭”是指撤销文件信息区和文件缓冲区,使文件指针变量不再指向该文件,显然就无法进行对文件的读写了。
打开文件 fopen(文件名,使用文件方式);
ANSI C规定了用标准输入输出函数fopen来实现打开文件。
fopen函数的调用方式为:
fopen(文件名,使用文件方式);
//打开文件函数,返回值是指向文件的指针,通常将其赋给一个指向文件的指针变量。
//打开文件需要告知编译系统3个信息:
//1.打开文件的名字;2.使用文件的方式;3.要赋予哪个指针。
使用文件方式
文件使用方式 |
含义 |
如果指定的文件不存在 |
“r”(只读) |
为了输入数据,打开一个已存在的文本文件 |
出错 |
“w”(只写) |
为了输出数据,打开一个文本文件 |
建立新文件 |
“a”(追加) |
向文本文件尾添加数据 |
出错 |
“rb”(只读) |
为了输入数据,打开一个二进制文件 |
出错 |
“wb”(只写) |
为了输出数据,打开一个二进制文件 |
建立新文件 |
“ab”(追加) |
向二进制文件尾添加数据 |
出错 |
“r+”(读写) |
为了读和写,打开一个文本文件 |
出错 |
“w+”(读写) |
为了读和写,建立一个新的文本文件 |
建立新文件 |
“a+”(读写) |
为了读和写,打开一个文本文件 |
出错 |
“rb+”(读写) |
为了读和写,打开一个二进制文件 |
出错 |
“wb+”(读写) |
为了读和写,建立一个新的二进制文件 |
建立新文件 |
“ab+”(读写) |
为读写打开一个二进制文件 |
出错 |
- 用“r”方式打开的文件只能用于向计算机输入数据,而且该文件应该已经存在,并存有数据,这样程序才能从文件中读数据。
- 用“w”方式打开的文件只能用于向该文件写数据(即输出文件)。若不存在该文件,则在打开文件前新建一个以指定的名字命名的文件。如果原来已存在一个以该文件名命名的文件,则在打开文件前先将该文件删去,然后重新建立新文件。
- 如果希望向文件末尾添加新的数据(不希望删除原有数据),则应该用“a”方式打开。打开文件时,文件读写位置标记移到文件末尾。//在每个数据文件中自动设置了一个隐式的“文件读写位置标记”,它指向的位置就是当前进行读写的位置。
- 用“r+”、“w+”、“a+”方式打开的文件即可用来输入数据,也可用来输出数据。用“r+”方式时该文件应该已经存在,以便计算机从中读数据。用“w+”方式则新建立一个文件,先向此文件写数据,然后可以读此文件中的数据。用“a+”方式打开的文件,原来的文件不被删去,文件读写位置标记移到文件末尾,可以添加,也可以读。
- 如果不能实现“打开”的任务,fopen函数将会带回一个出错信息。出错原因可能是:“r”打开不存在文件;磁盘故障;磁盘已满等。此时fopen函数将带回一个空指针值NULL(在stdio.h头文件中,NULL已被定义为0)。
常用下面的方式打开一个文件:
if((fp=fopen(“file1”,“r”))= =NULL)//先检查。打开文件的操作是否出错
{printf(“cannot open this file\n”);//若出错就输出无法打开
exit(0); //exit函数用于关闭所有文件,终止正在执行的程序,exit函数在stdlib.h中
} //待用户检查出错误,修改后重新运行
- C标准建议用上表列出的文件使用方式打开文件,但有些C编译不完全提供所有功能。
- 计算机从ASCII文件读入字符时,遇到回车换行符,系统把它转换为一个换行符,在输出时把换行符转换成为回车和换行两个字符。在用二进制文件时,不进行这种转换,在内存中的数据形式与输出到外部文件中的数据形式完全一致,一一对应。
- 程序中可以使用3个标准的流文件——标准输入流、标准输出流、标准出错输出流。系统已对这3个文件指定了与终端的对应关系。标准输入流是从终端的输入,标准输出流是向终端的输出,标准出错输出流是当程序出错时将出错信息发送到终端。
程序开始运行时系统自动打开这3个标准流文件。因此程序编写者不需要在程序中用fopen函数打开它们。所以以前我们用到的从终端输入或输出到终端都不需要打开终端文件。系统定义了3个文件指针变量stdin,stdout和stderr,分别指向标准输入流、标准输出流和标准出错输出流,可以通过这3个指针变量对以上3种流进行操作,它们都以终端作为输入输出对象。如果程序中指定要从stdin所指的文件输入数据,就是指从终端键盘输入数据。
关闭文件 fclose(文件指针);
在使用完一个文件后应该关闭它,以防止它再被误用。
fclose函数的调用形式为:
fclose(文件指针);
//关闭文件,函数带回一个值,当成功执行关闭操作,返回值为0,否则返回EOF(-1)
//若不关闭文件将会丢失数据。因为,在向文件写数据时候,是先将数据输出到缓冲区,待缓冲区充满才正式输出给文件。若缓冲区未满关闭文件,则可能造成数据丢失。因此要用fclose关闭文件,先把缓冲区中的数据输出到磁盘文件,然后才撤销文件信息区。有的编译系统在程序结束前会自动先将缓冲区中的数据写到文件,从而避免此问题,但还是应该养成在程序终止之前关闭所有文件的习惯。