文件介绍
文件这个概念,耳熟能详都能说上来几个,像什么 txt文件、word文件、Excel文件、图片、PDF、音视频文件等等,等等。
这些文件都有一个共同的特性就是能长久的保存数据,当程序退出时文件里的数据并不会随之消失。通常,这些文件被存储在的硬盘等上。我们将使用文件存放数据称为数据的持久化。
文件的分类
在软件开发中,通常我们将文件分为两种:程序文件 和 数据文件。
- 程序文件
程序文件指的是与程序编译链接有关的文件。这些文件主要包括:源文件(.c/.cpp等),目标文件(.obj)文件,可执行程序(.exe) - 数据文件
文件保存的是程序运行时读写的数据,比如配置文件(config.ini),图片(pic.png/pic.jpg)。这些文件通常关联的是程序运行或用户使用的文件。
文件的用途
数据的持久化、网络传输。比如保存数据、配置文件、前后端数据的交互等等。
文件名
一个文件要有一个唯一的文件标识(智能之前计算机和二义性只能活一个),以便用户识别和引用。
通常文件名由三部分组成:文件路径、文件名主干、文件后缀。
例如 C:\\Code\\file.txt
这里的 C:\\Code
就是文件的路径(path),file
是文件名主干(baseName),.txt
是文件后缀(suffix)。
在实际使用中我们都是以文件名主干代替文件名。没必要抬什么,知道什么时候用文件全名,什么时候用文件名主干就好了呀。
文件路径还涉及到两个问题:1.相对路径和绝对路径 2.window风格路径和linux风格路径
window和linux下不同的路径风格
我们常见的路径大抵有三种:
C:\Code\file.txt
C:\\Code\\file.txt
C:/Code/file.txt
前两种是Windows下使用的路径,第三种是linux系统使用的路径(posix风格)。
为什么Windows下使用的路径还有两种呢? 注意:\
是一个特殊字符,而 /
不是特殊字符。这就导致了如果windows风格的路径出现在了程序中且只有一个 \
那么你就必须再加一个 \
使得 \
完成转义。
::并非所有的window路径在程序中都需要使用两个 \
。但是两个反斜杠总不会错。现在windows也支持 /
。
相对路径和绝对路径
window下从盘符(C: / D: 等)开头的路径,linux下从根目录( / )开始写的路径都是绝对路径。相对于某个位置,如当前文件夹( . ) 开始的路径都是相对路径。
C:\Code\file.txt
绝对路径
/Code/file.txt
绝对路径
./Code/file.txt
相对路径
在相对路径中 .
表示当前路径,..
表示上级目录(上级路径)
文件指针
程序中操作文件,使用的是文件指针。
使用文件指针操作文件这件事情也容易理解,毕竟要是将使用的文件全部加载到内存中来,假设一个文件几十M,加载个十个八个,那开销显得太过惊人了。
文件指针是一个 结构体指针。当文件被使用时,系统会为每个被使用的文件开辟一个文件信息区,用来存放如,文件名、文件位置、文件大小、文件状态等信息。这些信息被保存在一个结构体变量 FILE 中。
- 文件信息区是一个结构体(FILE)类型的。
- FILE类型由系统声明,不同的编译器 FILE 类型的细节可能不完全相同,但无关紧要。作为开发人员不可深究三方库的实现。
- 文件信息区和文件是强绑定的,只要文件发生变化,文件信息区一定是随着发生变化的(这是文件系统实现的基础)。
- 打开文件时,系统就会根据文件的情况自动创建一个 FILE结构的变量,并填充数据。开发人员无需为文件信息区进行任何操作。
- 因为 FILE 结构体较大,传回这个结构体的首地址明显要比复制整个结构体并传回的效率高,因此FILE常以指针形式存在
//VS2013中的FILE类型
struct _iobuf {
char *_ptr;
int _cnt;
char *_base;
int _flag;
int _file;
int _charbuf;
int _bufsiz;
char *_tmpfname;
};
typedef struct _iobuf FILE;
//另一个FILE结构体
typedef struct
{
short level; /*缓冲区‘满’或‘空’的程度*/
unsigned flags; /*文件状态标志*/
char fd; /*文件描述符*/
unsigned char hold; /*如无缓冲区不读字符*/
short bsize; /*缓冲区的大小*/
unsigned char *buffer; /*数据缓冲区的位置*/
unsigned char *curp; /*指针当前的指向*/
unsigned istemp; /*临时文件指示器*/
short token; /*用于有效性检查*/
}FILE;
打开文件时,其实就是创建一个文件信息区,并与文件关联起来。
一般通过一个 FILE指针 来维护FILE结构的变量。
FILE* fp; //文件指针变量
pf 是一个指向FILE类型数据的指针变量。可以使pf指向某个文件的文件信息区。通过该文件信息区中的信息能够访问该文件。也就是说,通过文件指针变量能够找到与它关联的文件。
文件指针的获取
我们已经知道通过一个 FILE 指针(如: FILE* fp;)来维护一个 FILE 结构的变量,以此建立程序与文件之间的关联。而指针 fp 的值可以通过函数 fopen 获得。
FILE* fopen(const char* filename, const char* mode)
关于 fopen
函数我们需要知道以下几点:
- fopen 是打开一个文件,任何一个文件在使用(读写)之前都应被正确打开,在使用(读写)结束之后都应被正确关闭。
- fopen有两个
const char*
类型的参数,第一个参数表示文件名,第二个参数表示打开文件的模式,是只读的形式打开,只写的形式打开还是以什么形式打开。 - 文件的打开模式有
r(只读),w(只写),a(追加),b(二进制形式打开),+(增强模式)
- r只读,如果要打开的文件不存在报错
- w只写,文件不存在则创建;若文件存在且文件里有内容会清空文件中的内容再写入
- a追加,文件不存在则创建;若文件存在且文件里有内容会在原内容之后写入
- b二进制的形式打开。
- +模式增强,r+,w+增表示读写。不同点见r、w的区别。
- r、w互斥,因此要以读写的模式打开文件只能写r+或w+
- 文件是一种资源,一个进程(程序)能打开的文件是有限的,一个文件打开而不释放,就可能导致最后的文件无法打开的情况,因此文件必须被正确关闭。
- 文件的关闭函数:
fclose(FILE* stream)
文件在读写之前应该先打开文件,在使用结束之后应该关闭文件。
文件是一种资源,一个程序能打开的文件是有限的。建议不使用文件时进行文件的关闭。