1.为什么要使用文件
如果没有⽂件,我们写的程序的数据是存储在电脑的内存中,如果程序退出,内存回收,数据就丢失了。所以使用文件是为了将数据持久化地保存
2.什么是文件
文件是存储在某种长期储存设备或临时存储设备中的一段数据流,并且归属于计算机文件系统管理之下。所谓“长期储存设备”一般指磁盘、光盘、磁带等。
从文件功能的角度来区分分为程序文件和数据文件
2.1程序文件
程序⽂件包括源程序⽂件(后缀为.c),⽬标⽂件(windows环境后缀为.obj),可执⾏程序(windows 环境后缀为.exe)。
2.2数据文件
数据文件用于储存数据,供程序运行时储存数据或读取数据。
程序运行时读取数据可以由键盘输入读取

也可以由磁盘上的数据文件里读取
2.3文件名
文件名:文件路径 + 文件名主干 + 文件后缀

3.二进制文件和文本文件
根据数据的组织形式,数据⽂件可区分为⽂本⽂件或者⼆进制⽂件
数据在内存中以⼆进制的形式存储,如果不加转换的输出到外存,就是⼆进制⽂件。
如果要求在外存上以ASCII码的形式存储,则需要在存储前转换。以ASCII字符的形式存储的⽂件就是⽂本⽂件。
4.文件的打开和关闭
4.1流和标准流
4.1.1流
我们程序的数据需要输出到各种外部设备,也需要从外部设备获取数据,不同的外部设备的输⼊输出 操作各不相同,为了⽅便程序员对各种设备进⾏⽅便的操作,我们抽象出了流的概念,我们可以把流想象成流淌着字符的河。

4.1.2标准流
为什么我们平时输入输出的时候感受不到流呢?
因为C语⾔程序在启动的时候,默认打开了3个流:
-stdin : 标准输⼊流,在⼤多数的环境中从键盘输⼊,scanf函数就是从标准输⼊流中读取数据。
-stdout :标准输出流,⼤多数的环境中输出⾄显⽰器界⾯,printf函数就是将信息输出到标准输出 流中。
-stderr : 标准错误流,⼤多数环境中输出到显⽰器界⾯。
stdin、stdout、stderr 三个流的类型是: FILE* ,通常称为⽂件指针。 C语⾔中,就是通过 FILE* 的⽂件指针来维护流的各种操作的。
4.2文件指针
每个被使⽤的⽂件都在内存中开辟了⼀个相应的⽂件信息区,⽤来存放⽂件的相关信息(如⽂件的名 字,⽂件状态及⽂件当前的位置等)。这些信息是保存在⼀个结构体变量中的。该结构体类型是由系统声明的,取名FILE
例如,VS2013编译环境提供的 stdio.h 头⽂件中有以下的⽂件类型申明:
struct _iobuf {
char *_ptr;
int _cnt;
char *_base;
int _flag;
int _file;
int _charbuf;
int _bufsiz;
char *_tmpfname;
};
typedef struct _iobuf FILE;
不同的C编译器的FILE类型包含的内容不完全相同,但是⼤同⼩异。
每当打开⼀个⽂件的时候,系统会根据⽂件的情况⾃动创建⼀个FILE结构的变量,并填充其中的信 息,使⽤者不必关⼼细节。
⼀般都是通过⼀个FILE的指针来维护这个FILE结构的变量,这样使⽤起来更加⽅便。 下⾯我们可以创建⼀个FILE*的指针变量:
FILE* fp;//文件指针变量
定义fp是⼀个指向FILE类型数据的指针变量。可以使fp指向某个⽂件的⽂件信息区(是⼀个结构体变 量)。通过该⽂件信息区中的信息就能够访问该⽂件。也就是说,通过⽂件指针变量能够间接找到与它关联的⽂件。
如图:
4.3C语言程序中文件的打开和关闭
c语言程序中要对文件进行操作,需要对文件进行打开,使用完后要关闭
打开文件需要用到函数
fopen
有以下打开方式
若指定文件不存在就在当前目录创建一个文件
如下例子:
#include<stdio.h>
int main()
{
//打开文件
FILE* pf = fopen("date.txt","w");
if(pf == NULL)
{
//打开失败返回1
return 1;
}
//向文件写入数据
fputs("fopen ",pf);
//关闭文件
fclose(pf);
pf = NULL;
return 0;
}
5.文件的顺序读写
5.1 文件的顺序读写的函数
fgetc 与 getchar 、fputc 与 putchar 、 fgets 与 gets 、 fputs 与 puts 、fscanf 与 scanf 、fprintf 与 printf 的使用很相似,不同点为后者们为对标准输入/输出(键盘/屏幕)进行操作,前者们为对文件进行输入/输出,在此不详细介绍
fread以二进制格式读取文件,读取count个大小为size字节的元素,将数据放入ptr指向空间中
fwrite将ptr指向空间的count个s大小为ize字节的元素以二进制格式写入文件
举例:
char * fgets ( char * str, int num, FILE * stream );//与gets的使用方法相似,从文件读取字符串
FILE* pf = fopen("date1.txt", "r");
char arr[10] = { 0 };
fgets(arr, 10, pf);//从pf所指向的文件里读取10个字符
int fscanf ( FILE * stream, const char * format, ... );//与scanf的使用方法相似,以指定格式从文件里读取数据
struct Stu s = { "zhangsan",18,90.5 };
FILE* fp = fopen("date2.txt", "r");
struct Stu s2 = { 0 };
fscanf(fp, "%s %zd %f", s2.name, &s2.age, &s2.score);//按格式读取文件里的数据赋给结构体s2
6.文件缓冲区
ANSIC 标准采⽤“缓冲⽂件系统”处理的数据⽂件的,所谓缓冲⽂件系统是指系统⾃动地在内存中为 程序中每⼀个正在使⽤的⽂件开辟⼀块“⽂件缓冲区”。从内存向磁盘输出数据会先送到内存中的缓 冲区,装满缓冲区后才⼀起送到磁盘上。如果从磁盘向计算机读⼊数据,则从磁盘⽂件中读取数据输 ⼊到内存缓冲区(充满缓冲区),然后再从缓冲区逐个地将数据送到程序数据区(程序变量等)。缓 冲区的⼤⼩根据C编译系统决定的。
因为有缓冲区的存在,C语⾔在操作⽂件的时候,需要做刷新缓冲区或者在⽂件操作结束的时候关闭⽂ 件。 如果不做,可能导致读写⽂件的问题。