在电脑上,我们经常看到各种后缀的文件,比如.jpg .zip .exe .txt等等
这些文件的后缀虽然不同,但是他们都是文件。
一、为什么要有文件的存在?
每次我们在使用word/excel/ppt的时候,总会在我们退出的时候,跳出一句“是否保存文件?”
”保存“就成了文件的目的,我们需要将所编写的程序保存下来,以便下次使用/修改。
二、文件的分类
程序文件
程序文件,我们最熟悉的.c文件就是一种程序文件,还有目标文件(.obj文件),可执行文件(.exe文件)。
数据文件
文件内容不一定是程序,也可以是程序运行时读写的数据。
而我们讨论的,正是数据文件。
以前,我们总是通过scanf将数据输入到程序里,实际上这是终端输入。我们之前的输入输出都是以终端为对象,即从终端的键盘输入数据,运行结果显示到显示器上。
其实,我们有时候会把信息放到磁盘里,在使用时,再读取到内存里,而数据文件正是我们所需要的。
数据文件的分类
根据数据的组织形式,数据文件被称为文本文件或者二进制文件。
数据在内存中以二进制形式储存,如果不转换便输出到外存的文件中,就是二进制文件(换句话说,如果你点开一个数据文件全是乱码,基本就是二进制文件了)
如果以ASCII码储存,则需要在储存前转换,这种就是文本文件。
字符在文件中一律按ASCII码形式储存,而数值型数据既可以用ASCII形式储存,也可以用二进制形式储存。
文件的打开和关闭
流
流,不是一个具体的东西,而是一个抽象概念。我们可以将其想象成都是字符的河流。
一般情况下,我们要想向流里写数据,或者读数据,都是打开流,然后才能操作
标准流
我们从键盘上输入数据,向屏幕上输出数据,却并没有打开流。
原因是C语言程序在启动时默认打开以下三个流:
stdin-标准输入流
stdout-标准输出流
stderr-标准错误流
默认打开这三个流,我们可以直接通过scanf,printf函数直接进行输入输出操作。
而这三个流的类型是:FILE*,也被称为文件指针
文件指针FILE*
每个被使用的文件都在内存中开辟了一个相应的文件信息区。而文件指针既然是一个指针,就是为了指向这些文件的。
而这些文件的信息,会被储存在一个结构体变量中,统一取名为FILE。
我们可以通过stdio.h,找到对FILE的定义(寻找名字为FILE的声明即可)
作为指针,我们就可以用指针的方式来初始化、赋值等等。比如:
FILE* pf=NULL;
我们就可以通过pf这个指针来访问对应的文件了。
文件的打开和关闭
根据前文提到,我们只会默认打开三个流,其他的流(或者文件)需要我们自己打开。
这个时候我们就需要fopen和fclose两个函数来打开/关闭文件。
需要注意的是,fopen的返回类型是FILE*,fclose的返回类型是int。
FILE*fopen(const char* filename, const char*mode);
int fclose(FILE*stream);
而fopen里的参数mode表示文件的打开模式
比如我需要”写“一个函数,我就可以写成:
FILE*pf=fopen("test.txt","w");(但是注意的是,如果我们使用w,文件里原先存储的数据会被清除)
同时,我们在打开文件后,可以对文件进行一系列的操作。
操作完之后,我们要记得关闭文件。
fclose(pf);
对文件进行操作
我们不能只打开/关闭文件,因为那样毫无意义。
所以我们需要以下函数:
还有一些文件操作函数:
fseek:根据文件指针的位置和偏移量来定位文件指针(文件内容的光标)。
ftell:返回文件指针相对于起始位置的偏移量
rewind:让文件指针的位置回到文件的起始位置
以上便是一些关于文件操作的函数。和没有f的版本效果类似。
文件读取结束的判定
feof
讲之前,先牢记一点:feof的返回值不能直接用于判断文件是否读取结束。
feof的工作原理是,站在光标的位置向后看字符,如果仍有,那就返回0,如果没有,那就返回非0.
但有一种情况,让人烦恼。
如果feof传的指针指向的文件为空,但实际上此刻文档里存在一个EOF(每个文档和程序的末尾都存在一个EOF),这个时候,feof仍然会返回0(因为它认为有字符,实际上没有字符)。
所以我们需要移动光标一位,才能知道是否是真的到尾部了(如果到尾端,相当于跳过了EOF,如果没到,至少还有一个EOF)。