引言:
程序的本质作用之一,就是处理数据。若仅限于从控制窗口输入,那么是不能真正地实现处理数据,仅是实现了数据处理的功能。当程序能够与文件结合起来时,才真正地实现了对数据的处理。
零. 文件的分类
文件是指存储在外部介质上的数据集合,从用户角度上看,文件可以分为磁盘文件和标准输入输出文件。常用的磁盘文件按照处理方法的不同又可分为缓冲文件系统和非缓冲文件系统。ANCI C(常说的C语言标准,例如C89)重点研究缓冲文件系统。根据文件中数据的存储形式不同,又可以将文件分为文本文件和二进制文件。
1.磁盘文件与标准输入输出文件:
磁盘文件可以简单的理解为,是用户拿到电脑后,用户自己可以处理操作的文件;而标准输入输出文件则是系统默认好的文件,例如:标准输入文件(通常指键盘,用文件指针stdin指向。standard(std):标准),标准输出文件(通常指显示器,用文件指针stdout指向),标准出错输出文件(一般也指显示器,用文件指针stderr指向)。
2.缓冲文件系统:
对于缓冲文件系统,在每打开一个文件时,系统都会在内存中自动开辟一个缓冲区,缓冲区的大小不同由C语言版本决定,一般为512字节。数据先被送入缓冲区,待缓冲区满后,再向内存或磁盘传送。
3.文本文件与二进制文件
程序运行处理及产生的数据都是二进制,一串又一串的0与1,直接想要读懂是难上加难再加难,因此就有了文本文件(ASCII文件或text文件),将二进制数据处理后展现出来,以便人们的阅读。也就是说文本文件与二进制文件仅是不同的存储方式:
二进制文件(.bin)
优点:
①节省内存:
例如:100在文本文件中是分做三个字符‘1’,‘0’和‘0’,一个字符两个字节,那么至少需要6个字节,而在二进制文件中,若该100是int整形,则仅需4个字节,数据越大,差距就越明显。
②处理速度快:
上述已说,文本文件是二进制通过转化的来的,故可得:对二进制文件的处理是直接的,而对文本文件的处理是间接的。
③精度高
在二进制文件转化文本文件的过程中,有效位会有丢失,而直接以二进制文件存储处理,就不会发生该情况。
缺点:
①看不懂。
2.文本文件(.txt 、.p、.c、.cpp……)
和上述二进制文件都刚好相反。
一.文件指针
文件指针是贯穿缓冲文件系统的主线,一个文件指针是指向文件有关信息的指针。在C语言中,一个文件的有关信息都被整合在了一个默认的结构体中:FILE(该结构体已经在头文件stdio.h中说明),那么文件指针就是一个指向 FILE类型的结构体 的 指针。
定义:
FILE *fp;
为了提高程序的可读性,可以将输入文件定为fin,输出为fout等等。同样的,也可以定义一个文件指针组,例如:FILE *fin[N],同时定义了N个输入文件的指针。
注:这里操作的都是数据文件。
二.文件的打开
1.函数:
FILE *(char *filename, char *mode)
顾名思义:第一个参数是文件名,但是文件名也略有讲究:一个合格的文件名应包括三大部分:文件路径+文件主名+文件后缀;例如:c:\temp\text1.txt,但是在使用函数的时候可以不写文件路径,不写时,程序默认路径为当前工作路径。第二个参数是打开方式:
注:
二进制文件打开方式后面多的b就是bin的开头(●’◡’●)。
这里一般不使用+的模式,专一一些,少些问题。
2.代码展示:
注:
因为双撇号括起来的字符串中“\”开始表示转义字符,如果要表示路径中的斜杠,必须用双斜杠“\\”。
这里的报错是一个格式化代码,一般打开文件,不论哪种方式,都可以写上(fopen函数在当打开失败时,其会返回NULL)。
这里的文件名,还可以是定义的一个字符数组变量(字符串),实现打开指定的文件。该情况下文件默认是在当前工作路径下。
3.对打开文件的理解:
当执行打开文件的命令时,系统会干3件事:①建立一个文件相应的信息区,②开辟相应的文件缓冲区,③实现将文件的内容从磁盘上读入到内存缓冲区。
三.文件的关闭
1.函数:
int fclose(FILE *fp)
关闭成功返回0,否则非0(不同编译器可能不一样,大多是-1,会有一个符号常量EOF来表示-1)。
2.代码:
3.对关闭文件的理解:
当执行关闭文件的命令时,系统会干3件事:①将使用完的文件从缓冲区中写回磁盘,②切断缓冲区与该文件所有联系,③释放文件缓冲区(缓冲文件系统自带的)。
4.注意注意注意:
打开文件后一定得关,就像malloc了一些堆区内存后一定得free!!!
四.文件的读(下文的fp均与上文定义的fp意义一致)
前文讲到,键盘的输入是一种标准输入输出文件,因此,以前使用的各种输入函数都是文件读取函数的特殊情况。
注:以下函数都得在读或读写的模式下打开(r,r+等)。
1.读字符函数fgetc(对应getchar):
①原型:
int fgetc(FILE *pf)
②用法:
注:
从fp指向文件的当前位置读取一个字符,并将文件位置指针后移。
若读入的为文件结束符或出错时,返回EOF。
③和getchar()的对比:
getchar()和fgetc(stdin)等价。
2.读字符串函数fgets(对应gets):
①原型:
char *fgets(char *buf, int n , FILE *fp)
②用法:
注:
最多只可读取n-1个字符,末尾添加‘\0’。
该函数在非文件处理下应用也较为广泛,gets函数是遇到‘\n’终止读取(且自动删除‘\n’),有潜在危险,应用的是
③和gets对比:
gets()与fgets(str,n,stdin)约等,有差别。
3.格式化读fscanf(和scanf对应):
①用法(原型有点抽象):
即在scanf函数的参数前面加上一个文件指针,指明从哪里读。
②和scanf对比:
fscanf(stdin,”%d”,&n)和scanf(“%d”,&n)是等价的。
五.文件的写
同文件的读,以前使用的各种输入函数都是文件读取函数的特殊情况。
注:以下函数都得在写或读写的模式下打开(w,w+等)。
1.写字符fputc(和putchar对应):
①原型:
int fputc(char ch, FILE *fp);
②用法:
注:
操作失败返回EOF。
③和putchar()对比:
putchar(c)和fputc(c,stdout)等价。
2.写字符串fputs(对应puts)
①原型:
int fputs(char *str, FILE *fp)
②用法:
③和puts()对比:
puts(c)和fputs(c,stdout)等价。
3.格式化写fprintf(和printf对应):
①用法(原型有点抽象):
即在printf函数的参数前面加上一个文件指针,指明从哪里读。
②和printf()对比
printf(“%d”,n)和fprintf(fp,”%d”,n)等价。
END
文件是程序处理的本质,了解文件的处理有助于对深层且实用性更强的程序以及数据库的掌握。!!!(文件的数据块读写,随机读写下次见)