目录
什么是文件?
为什么使用文件?
程序文件和数据文件、文本文件和二进制文件
1.程序文件和数据文件
1.1程序文件
1.2数据文件
2.文本文件和二进制文件
文件的打开和关闭(流、标准流、文件指针和文件的打开与关闭)
1.流和标准流
1.1:流
1.2:标准流
2.文件指针
3.文件的打开和关闭
例:"w"——只写(从文件输出数据)
关闭文件
文件的顺序读写和随机读写
1.文件的顺序读写
1.1:顺序读写的函数介绍
1.2:fputc函数
1.3:fgetc函数
1.4:fputs和fgets函数
对比三组函数
2.文件的随机读写
2.1:fseek
2.2:ftell
2.3:rewind
文件读取结束的判定
1.feof
2.文件读取结束的判定
文件缓冲区
什么是文件?
磁盘(硬盘)上的文件是文件。
可能有点抽象,举个例子,如图:
图中所有的文件包括文件夹都是文件。
而为了使用文件,自然也需要文件名来让我们进行识别和引用。
文件名包含三部分:文件路径 + 文件名主干 + 文件后缀
例如:c:\code\test.txt
为什么使用文件?
首先要知道,我们写的程序的数据是存储在电脑的内存中的,如果没有文件,程序退出内存回收,数据就丢失了,等再次运行程序就无法看到上次程序的数据。
而文件可以将数据进行持久化保存。
因此如果要将数据进行持久化的保存,我们可以使用文件。
程序文件和数据文件、文本文件和二进制文件
1.程序文件和数据文件
在程序设计中,我们一般谈的文件有两种(从文件功能的角度来分类的):程序文件和数据文件
1.1程序文件
程序文件(按我的理解)口语化一点的讲就是我们写的代码那些所产生的文件。——
比如我们写代码就是在.c文件写的,编译后产生的就是.obj(目标)文件,链接后就是.exe文件。
都是我们编写的代码所产生的文件(或者在文件中编写的代码)
程序文件包括源程序文件(后缀为.c)、目标文件(windows环境后缀为.obj)和可执行程序(windows环境后缀为.exe)。
1.2数据文件
文件的内容不一定是程序,而是程序运行时读写的数据,比如程序运行需要从中读取数据的文件,或者输出内容的文件。
我们之前基本都是以程序文件的形式运行代码的,而本章主要讨论的就是数据文件了。
2.文本文件和二进制文件
根据数据的组织形式(按内容分),数据文件又被称为文本文件或二进制文件
数据在内存中以二进制的形式存储,如果不加转换的输出到外存的文件中(也就是直接输出了),就是二进制文件。
如果要求在外存上以ASCII码的形式存储,则需要在存储前转换。以ASCII字符的形式存储的文件就是文本文件。
文件的打开和关闭(流、标准流、文件指针和文件的打开与关闭)
1.流和标准流
1.1:流
当我们写个程序要输出到外部设备上,或者要从外部设备读取数据时,外部设备不同,输入输出操作自然也可能不同,因此为了方便我们操作,就产生了流。
C程序针对文件、画面、键盘等的数据输入输出都是通过对流操作的。
我们可以把流当作中介,一般当我们要向流里写数据,或者从流中读取数据时,都是打开流然后进行操作。
有小伙伴可能会问了,我们这题目明明是“题目的打开和关闭”,为什么要突然讲流和标准流呢?
其实不难想到,文件我们上文讲过是用来将数据进行持久化保存的——也就是说,文件里面放的也是数据,而文件的打开和关闭即文件的使用,文件的使用不管是读取还是输出数据,都要经过我们的流来进行数据的输入输出,因此流是我们学习文件使用的基础,所以先对流进行讲解,下文中的标准流、文件指针等也是同理。
1.2:标准流
我们上文中讲了“C程序针对文件、画面、键盘等的数据输入输出都是通过对流操作的。”,可我们从键盘输入数据并从屏幕上输出数据时并没有打开流,直接使用scanf、printf等函数就可以直接进行输入输出操作了,这是为什么呢?——
这都是因为C程序在启动时已经默认打开了三个流:
- stdin - 标准输入流 ,在大多数的环境中从键盘输入,scanf函数就是从标准输入流中读取数据。
- stdout - 标准输出流,大多数环境中输出至显示器页面,printf函数就是将信息输出到标准输出流中。
- stderr - 标准错误流,大多数环境中输出到显示器页面。
stdin、stdout和stderr三个流的类型都是:FILE*,通常称为文件指针。
C语言中,就是通过FILE* 的文件指针来维护流的各种操作的。
2.文件指针
其实是叫“文件类型指针”,简称文件指针。
文件存放着数据,文件被使用时本身也是数据,因此被使用的文件都在内存中开辟了一个相应的文件信息区,用来存放文件的相关信息(如文件名、文件位置等)。
而这些信息是保存在一个结构体变量中的。该结构体类型则由系统声明,取名FILE。
如下图:
一般都是通过一个FILE的指针来维护这个FILE结构的变量。(也就是通过一个指向FILE的指针来对与FILE有关联的文件进行访问)。
3.文件的打开和关闭
当我们开始对文件打开与关闭时应该就是要使用(读写)我们的文件了——使用文件的步骤可以分三步:
- 打开文件(其实就是打开流)
- 读/写文件
- 关闭文件(其实就是关闭流)
ANSI C规定使用fopen函数来打开文件,fclose函数来关闭文件。
如图分别为在cplusplus中找到的两个函数的介绍:
在编写程序的时候,打开文件的同时都会返回一个FILE*的指针变量指向该文件,也相当于建立了指针和文件的关系。如图:
mode表示文件的打开方式(即读/写/······)。下面都是文件的打开方式:
例:"w"——只写(从文件输出数据)
假设我们此时要写一个文件test.txt,如图:
但此时我们的文件夹并没有text.txt这个文件,此时的文件夹如下图:
但是当我们运行代码后,就在文件夹中产生了一个text.txt文件,如下图示:
关闭文件
前文有讲过:我们关闭文件要用fclose函数,但是关闭后我们还需要手动置为空指针
如图:
此时我们经过调试,可以看到,指针pf经fclose函数关闭后,还是有地址,只是不指向文件了,因此此时的pf指针是野指针,所以我们要手动将其置空指针。
文件的顺序读写和随机读写
1.文件的顺序读写
1.1:顺序读写的函数介绍
顺序读写的函数介绍如下图:
上图中的适用于所有输入流一般指的是适用与标准输入流和其他输入流(如文件输入流),
适用于所有输出流也同理(标准输出和其他输出)。
1.2:fputc函数
由上图我们可以知道,fputc为字符输出函数,函数形式如下(函数的具体功能可以自行前往fputc - C++ Reference (cplusplus.com) 查看):
函数有了解之后我们就接着按三板斧来进行实现了,函数实现如下:
int main()
{
//1.打开文件
FILE* pf = fopen("text.txt", "w");
if (pf == NULL)
{
perror(fopen);
return 1;
}
//2.使用(写)文件
fputc('a', pf);
fputc('b', pf);
fputc('c', pf);
fputc('d', pf);
fputc('e', pf);
//3.关闭文件
fclose(pf);
pf = NULL;
return 0;
}
运行后我们就已经将abcde写入了文件text.txt中。
原本该文件是我们在上文中新建的内容为空,此时内容为"abcde"如下图所示:
1.3:fgetc函数
fgetc为字符输入函数,函数形式如下:
函数实现效果如下:
因为上文中我们已经往文件text.txt中写入了abcde,因此现在读四次读出来的是abcd。
1.4:fputs和fgets函数
这两个函数和上文刚刚讲的fputc和fgetc函数类似,此处就直接举例说明(fputs函数)了,如图:
如上图,fputs是进行写字符串操作的,将字符串写入pf指向的内容(此图指向的为text.txt文件中)
但是写字符串是连续的,如果希望换行需要自己在字符串末尾加\n.
fgets函数就相对复杂一点点,函数形式如下图:
此时我们text.txt文档内的放置内容为abcdef
fgets示例如下:
对比三组函数
scanf/printf —— 针对标准输入/输出流的 格式化 输入/输出函数
fscanf/fprintf —— 针对所有输入/输出流的 格式化 输入/输出函数
sscanf/sprintf —— 从字符串中读取格式化的数据 / 将格式化的数据写到字符串中
后面的四个函数就不过多赘述了,详细功能可以自行在cplusplus网址
(Reference - C++ Reference (cplusplus.com))中查找
2.文件的随机读写
2.1:fseek
根据文件指针的位置和偏移量来定位文件指针(文件内容的光标)。
文件的第三个参数(起始位置)如下:
示例:
int main()
{
//1.打开文件
FILE* pf = fopen("text.txt", "wb");
if (pf == NULL)
{
perror(fopen);
return 1;
}
//2.使用(写)文件
fputs("This is an apple.", pf);
fseek(pf, 9, SEEK_SET);
fputs(" sam", pf);
//3.关闭文件
fclose(pf);
pf = NULL;
return 0;
}
2.2:ftell
返回文件指针相较于起始位置的偏移量,形式如下:
这个就比较好理解了,我们直接上示例:
2.3:rewind
让文件指针的位置回到起点位置,形式如下:
我们在上图示例代码的基础上,再加入rewind观察,如下图所示:
文件读取结束的判定
1.feof
在文件读取过程中,不能用feof直接判断文件读取是否结束
feof是在当文件读取结束的时候,判断读取结束的原因是否是:遇到文件尾结束(也就是是否是正常读完的)。
2.文件读取结束的判定
- 判定文本文件读取是否结束时:
判断返回值是否为EOF(fgetc),
或NULL(fgets)。
- 判定二进制文件时
判定返回值是否小于实际要读的个数(fread)。
文件缓冲区
ANSIC标准采用“缓冲文件系统”处理数据文件的,
缓冲文件系统是指系统自动地在内存中为程序中每一个正在使用的文件开辟一块“文件缓冲区”。
从内存向磁盘输出数据会先送到内存中的缓冲区,装满缓冲区后才一起送到磁盘上。
如果从磁盘向计算机读入数据,则从磁盘文件中读取数据输入到内存缓冲区(充满缓冲区),然后再从缓冲区逐个地将数据送到程序数据区(程序变量等)。
缓冲区的大小时根据C编译系统决定的。
图示如下:
正是因为缓冲区的存在,所以我们在文件操作结束后才需要关闭文件,如果没有关闭可能导致读写文件的问题。
创作不易,如果觉得作者写的还行的话给个免费的三连吧亲🌹🌹