随风而动,随遇而安......
C语言文件-学习三十一
为什么要引入文件
- 数据量大
- 数据访问频繁
- 程序结果需要长期保存
使用文件的目的
- 1.程序与数据分离:数据文件的改动不引起程序的改动;
- 2.数据共享:不同程序可以访问同一数据文件中的数据;
- 3.能长期保存程序运行的中间数据或结果数据。
文件
- “文件”指存储在外部介质上数据的集合
- 一批数据是以文件的形式存放在外部介质上的
- 操作系统是以文件为单位对数据进行管理
- 想找存放在外部介质上的数据,先按文件名找到指定的文件,然后再从该文件读数据
- 要向外部介质上存储数据也必须先建立一个文件(以文件名作为标志),才能向它输出数据
输入输出是数据传送的过程,数据如流水一样从一处流向另一处,因此常将输入输出形象地称为流(stream),即数据流。流表示了信息从源到目的端的流动。
- 输入操作时,数据从文件流向计算机内存
- 输出操作时,数据从计算机流向文件
- 从C程序的观点来看,无论程序一次读写一个字符,或一行文字,或一个指定的数据区,作为输入输出的各种文件或设备都是统一以逻辑数据流的方式出现的。
- C语言言把文件看作是一个字符(或字节)的序列。输出流就是一个字符流或字节(内容为二进制数据)流。
- C的数据文件由一连串的字符(或字节)组成,而不考虑行的界限,两行数据间不会自动加分隔符,对文件的存取是以字符(字节)为单位的。
输入输出数据流的开始和结束仅受程序控制而不受物理符号(如回车、换行符)控制,这就增加了处理灵活性。这种文件称为流式文件。
文件名
文件要有一个唯一的文件标识,以便用户识别和引用。
文件标识包括三部分:
- 1.文件路径
- 2.文件名主干
- 3.文件后缀
文件路径表示文件在外部存储设备中的位置。
例如:
C:\VS\temp\file1.dat
C:\VS\temp\
文件路径file1
文件名主干 (命名规则遵循标识符的命名规则).dat
文件后缀 (doc、txt、dat、c、cpp、obj、exeopt、 bmp等)
文件的分类
按存储介质:
- 普通文件:存储介质文件(磁盘、磁带等设备文件)
- 设备文件:非存储介质(键盘、显示器等设备文件)
按数据的组织形式:
文本文件:ASCII文件,每个字节存放一个字符的ASCII码
- 文本文件特点:存储量大、速度慢、便于对字符操作
二进制文件:数据按其在内存中的存储形式原样存放
- 文本文件特点:存储量小、速度快、便于存放中间结果
例如:
- int型数 10000
- 内存存储形式:
0010011
00010000
存储以文本文件形式:
1
0
0
0
0
- 分别以 1 和 0 的 ASCII码 的形式与下面对应
0110001
00110000
00110000
00110000
00110000
- 存储以二进制文件形式:
0010011
00010000
(与内存存储形式一致)
文件缓冲区
- ANSI C标准采用“缓冲文件系统”处理数据文件
- 缓冲文件系统是指系统自动地在内存区为程序中每一个正在使用的文件开辟一个文件缓冲。
- 从内存向磁盘输出数据,必须先送到内存中的缓冲区,装满缓冲区后才一起送到磁盘去
文件类型指针
- 每个被使用的文件都在内存中开辟一个相应的文件信息区,用来存放文件的有关信息(如文件的名字、文件状态及文件当前位置等)。
- 这些信息是保存在一个结构体变量中的,该结构体类型是由系统声明的,取名为FILE。
- 例如:
在stdio.h头文件中有以下的文件类型声明:
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 *fp
- 例如:
- 文件打开时,系统自动建立文件结构体,并把指向它的指针返回来,程序通过这个指针获得文件信息,访问文件。
- 文件关闭后,它的文件结构体被释放。
打开和关闭文件
- C文件操作用库函数实现,包含在stdio.h
- 文件使用方式:打开文件 --> 文件读/写 --> 关闭文件
系统自动打开和关闭三个标准文件:
- 标准输人-----键盘
stdin
- 标准输出-----显示器
stdout
- 标准出错输出-----显示器
stderr
- 标准输人-----键盘
用fopen函数打开数据文件
- “打开”是指为文件建立相应的信息区(用来存放有关文件的信息)和文件缓冲区(用来暂时存放输入输出的数据)。
- 在编写程序时,在打开文件的同时,一般都指定一个指针变量指向该文件,也就是建立起指针变量与文件之间的联系,这样就可以通过该指针变量对文件进行读写。
函数原型:
FILE *fopen(char *name , char *mode);
char *name
要打开文件的名字char *mode
使用文件的方式(读、写、读写)
- 返回值:正常打开,返回指向文件结构体的指针;打开失败,返回NULL。
fopen函数参数中的文件名可以带文件路径,但是文件路径中的“\”必须使用转义字符。
例如:
要打开在路径为
C:\VS\temp\file1.dat
的文件应该写成:fopen("C:\\VS\\temp\\file1.dat","r");
mode 的值可以是下列值中的一个
模式 | 描述 |
---|---|
r | 打开一个已有的文本文件,允许读取文件。 |
w | 打开一个文本文件,允许写入文件。如果文件不存在,则会创建一个新文件。在这里,您的程序会从文件的开头写入内容。如果文件存在,则该会被截断为零长度,重新写入。 |
a | 打开一个文本文件,以追加模式写入文件。如果文件不存在,则会创建一个新文件。在这里,您的程序会在已有的文件内容中追加内容。 |
r+ | 打开一个文本文件,允许读写文件。 |
w+ | 打开一个文本文件,允许读写文件。如果文件已存在,则文件会被截断为零长度,如果文件不存在,则会创建一个新文件。 |
a+ | 打开一个文本文件,允许读写文件。如果文件不存在,则会创建一个新文件。读取会从文件的开头开始,写入则只能是追加模式。 |
如果处理的是二进制文件,则需使用下面的访问模式来取代上面的访问模式:
"rb"
,"wb"
,"ab"
,"rb+" 或 "r+b"
,"wb+" 或 "w+b"
,"ab+" 或 "a+b"
说明:
1.用“r”方式打开一个文本文件,只能用于向计算机输入,而不能用作向该文件输出数据,
而且该文件应该已经存在,并存有数据,这样程序才能从文件中读数据。- 不能用“r”方式打开一个并不存在的文件,否则出错。
- 为输入打开一个二进制文件,用“rb”。
2.用“w”方式打开一个文本文件,只能用于向该文件写数据(即输出文件),而不能用来向计算机输入。
- 如果原来不存在该文件,则在打开文件前新建一个以指定的名字命名的文件。
- 如果原来已存在一个以该文件名命名的文件,则在打开文件前先将该文件删去,然后重新建立一个文件。
- 为输出打开一个二进制文件,用“wb”。
3.如果希望向文件末尾添加新的数据(不希望删除原有数据),则应该用“a”方式打开。
- 但此时应保证该文件已存在;否则将得出错的信息。
- 打开文件时,文件读写标记移到文件末尾。
- 向二进制文件尾添加数据,用“ab”。
4.用 “r+、w+、a+ ” 方式打开的文本文件既可以用来输入数据,也可以用来输出数据。
- 如果是二进制文件用 “rb+、wb+、ab+ ”。
- 5.在向计算机输入文本文件时,会将回车换行符转换为一个换行符,在输出时把换行符转换成为回车和换行两个字符。
在用二进制文件时,不进行这种转换,在内存中的数据形式与输出到外部文件中的数据形式完全一致,一一对应。 - 6.如果打开失败,fopen函数将会带回一个出错信息。
fopen函数将带回一个空指针值NULL
- 常用下面的方法打开一个文件:
if ((fp = fopen("file1", "r")) == NULL) {
printf("Can not open this file\n");
exit(0); // 终止正在执行的程序
}
- 注意在VS中编译器会出现使用
fopen()
不安全,建议使用fopen_s()
的提示 格式:
fp=fopen("文件路径","模式");
fopen_s(&fp,"文件路劲","模式");
C标准建议用表列出的文件使用方式打开文本文件或二进制文件,但目前使用的一些C编译系统可能不完全提供所有这些功能。
比如:有的C版本只能用 “r",“w",“a" 方式,有的C版本不用 “r+”,“w+”,“a+",而用 “rw”,“wr",“ar” 等。
用fclose函数关闭数据文件
- “关闭”是指撤销文件信息区和文件缓冲区。
关闭文件用fclose函数。
fclose函数调用的一般形式为:fclose(文件指针);
例如:
fclose (fp);