文件是程序设计中一个重要的概念,所谓“文件”一般指存储在外部介质上数据的集合。
文件有不同的类型,在c程序设计中,主要用到两种文件程序文件,数据文件。
下面介绍一些有关文件的基本概念。
1.程序文件包括源程序文件(后缀为.c)、目标文件(后缀为.obj)、可执行文件(后缀为exe)等。这种文件的内容是程序代码
2.数据文件的内容不是程序,而是供程序运行时读写的数据。其根据数据的组织形式可分为文本文件和二进制文件
3.文件缓冲区:ANSI C标准采用“缓冲文件系统处理数据文件。系统自动地在内存区为程序中每一个正在使用的文件开辟一个文件缓冲区,在向文件输出数据时,它就作为输出缓冲区,数据“装满”缓冲区后一起送到磁盘。在从文件输入数据时,它就作为输入缓冲区,从磁盘读出一批数据,送到缓冲区,最后送到程序。
4.文本类型指针:每个被使用的文件都在内存中开辟一个相应的文件信息区,用来存放文件的有关信息。这些信息是保存在一个结构体变量中的,该结构体类型是由系统声明的,取名为FILE。例如有**一种c编译环境提供的stdio.h头文件中有以下文件类型声明:
typedef struct
{
short level; //缓冲区“满”或“空”的程度
unsinged flags; //文件状态标志
char fd; //文件描述符
unsigned char hold; //如缓冲区无内容不读取字符
short bsize; //缓冲区大小
unsigned char *buffer; //数据缓冲区的位置
unsiged char *curp; //文件位置标记指针当前的指向
unsigned istemp; //临时文件指示器
short token; //用于有效性检查
}FILE;
通过文件指针变量能够找到与它关联的文件,指向文件的指针变量指向内存中的文件信息区的开头
5.打开与关闭文件
所谓“打开”是指为文件建立相应的信息区和文件缓冲区。
ANSI C规定了用标准输入输出函数fopen来实现打开文件——fopen(文件名,使用文件方式)
如fopen("a1","r");
fopen函数的返回值是指向a1文件的指针变量(即a1文件信息区的起始地址)。通常将fopen函数的返回值赋给一个指向文件的指针变量。如FILE *fp;
fp=fopen("a1","r");
这样fp就和文件a1相联系了,或者说fp指向了文件。
使用文件的方式:
r:只读方式,文件必须存在
w:只写方式,若文件存在,则原有内容会被清除;若文件不存在,则会建立文件
a:追加方式打开只写文件,只允许进行写操作,若文件存在,则添加的内容放在文件末尾;若不存在,则建立文件
+:可读可写
b:以二进制方式打开文件
t:以文本方式打开文件(默认方式下以文本方式打开文件)
下面是常见的组合:
r: 以只读的方式打开文件,只允许读,此文件必须存在,否则返回NULL,打开成功后返回文件指针,位置指针指向文件头部
r+: 以可读可写的方式打开文件,允许读写,此文件必须存在,否则返回NULL,打开成功后返回文件指针,位置指针指向文件头部
rb+: 以可读可写、二进制方式打开文件,允许读写,此文件必须存在,否则返回NULL,打开成功后返回文件指针,位置指针指向文件头部
rt+: 以可读可写、文本方式打开文件,允许读写,此文件必须存在,否则返回NULL,打开成功后返回文件指针,位置指针指向文件头部
w: 以只写的方式打开文件,只允许写,若文件存在,文件中原有内容会被清除;若文件不存在,则创建文件,打开成功后返回文件指针,位置指针指向文件头部
w+: 以读写的方式打开文件,允许读写,若文件存在,文件中原有内容会被清除;若文件不存在,则创建文件,打开成功后返回文件指针,位置指针指向文件头部
a: 以追加、只写的方式打开文件,只允许写。若文件存在,则追加的内容添加在文件末尾,若文件不存在,则创建文件。打开成功后返回文件指针,位置指针指向文件头部(注意很多书上或资料上讲述追加方式打开成功后位置指针指向文件末尾是错误的)
a+: 以追加、可读写的方式打开文件,允许读写。若进行读操作,则从头开始读;若进行写操作,则将内容添加在末尾。若文件不存在,则创建文件。打开成功后返回文件指针,位置指针指向文件头部。
常用文件打开方式:
if((fp=fopen("file1","r"))==NULL){ printf("cannot open this file\n");exit(0);}
用fclose函数关闭数据文件
用法:fclose(文件指针),如
fclose(fp);
关闭文件的目的是防止结束程序时数据丢失。因为向文件写数据时,是先将数据输出到缓冲区,待缓冲区充满后才正式输出给文件,当数据未充满缓冲区时程序结束运行,有可能使缓冲区的数据丢失,用fclose函数关闭文件时,会先把缓冲区中的数据输出到磁盘文件,然后才撤销文件信息区。
fclose函数也带回一个值,当成功的执行了关闭操作,则返回为0,否则返回EOF(-1)。
6.顺序读写数据文件
对文本文件读入或输出一个字符的函数:
1.fgetc
调用形式:fgetc(fp)
,从fp指向的文件读入一个字符,读成功带回所读字符,失败则返回文件结束标志EOF
2.fputs
调用形式:fputc(ch,fp)
,把字符ch写到文件指针变量fp所指向的文件中,输出成功返回值就是输出的字符,输出失败则返回EOF。
在访问磁盘文件时,是逐个字符(字节)进行的,每访问完一个字节后,当前读写位置自动后移。为了知道对文件读写是否完成,即检测文件尾标志是否已被读取过(文件的所有有效字符后有一个文件尾标志,用标识符EOF表示)。用feof函数可检测文件尾标志是否被读取过,若已读过,返回值为1,否则为0。
对文本文件读入或输出一个字符串的函数:
3.fgets
调用形式:fgets(str,n,fp)
,即从fp指向的文件读入一个长度为(n-1)的字符串(最后加一个’\0’),存放到字符数组str中,返回值为地址str或NULL。
如果读完字符串之前遇到’\n’或EOF,读入结束,’\n’也作为一个字符读入。
4.fputs
调用形式:fputs(str,fp)
,即把str所指向的字符串写到文件指针变量fp所指向的文件中。输出成功,返回0,否则返回非0值。
7.用格式化的方式读写文本文件
对字符的输入输出前面已说明,怎么输入输出类型丰富的数据呢?
printf和scanf函数向终端进行格式化的输入输出。
fprintf和fscanf函数向文件进行格式化的输入输出。
1.一般调用方式
fprintf(文件指针,格式化字符串,输出表列)
fscanf(文件指针,格式化字符串,出入表列),如
fprintf(fp,"%d,%6.2f",i,f)fscanf(fp,"%d,%f",&i,&f);
8.用二进制方式向文件读写一组数据
fread(buffer,size,count,fp); 从文件读入count个size大小的数据项,放在地址buffer中。
fwrite(buffer,size,count,fp); 把从地址buffer开始的存储区中的数据向文件输出。
在读写时以二进制形似进行的,向磁盘写数据时,直接将内存中一组数据原封不动、不加转换的复制到磁盘文件上。
fread或fwrite函数的类型为int型,如果执行成功,则返回值为形参count的值,即输入或输出数据项的个数。
9.关于文件位置标记的函数
–rewind函数使文件位置标记指向文件开头,无返回值。rewind(fp)
–fseek(文件类型指针,位移量,起始点),如fseek(fp,100L,0);
将文件位置标记向前移到离开头100个字节处fseek(fp,50L,1);
将文件位置标记向前移到离当前位置50个字节处fseek(fp,-10L,2);
将文件位置标记从末尾处向后退10个字节