目录
一、文件名
在计算机上,每个文件都有一个自己的文件名。形如:“sky.jpeg”。一般文件名都是分为两个部分:①sky 名字 ②.jpeg扩展名
扩展名的用处:①区分文件的种类 ②高速操作系统使用哪个程序来默认打开这个文件,更准确的说,在系统上,是通过文件的“路径”作为文件的身份标识.
二、文件路径
2.1绝对路径
形如:D:\program\ha\haha.exe
2.2相对路径
需要给出一个“参考系”,告诉我们从哪个目录出发来找这个文件
如果以D:\program\ha作为参考系 此时.\haha.exe就为相对路径
2.3注意事项
\称为反斜杠 /称为斜杠
D:/program/ha/haha.exe这样的写法也是可以的,在Linux/Mac上,只支持/作为分割符.
更推荐使用/。
\容易和其他字符结合转义,所以不推荐,例如printf("D:\program\test");
三、为什么使用文件
因为“持久化”,持久化就是让数据一直持续的存储下去,写入磁盘/文件中这就是一个做简单但是又最常用的解决方案。(磁盘的数据也会丢失,一般是几年--几十年)
四、文件的分类
从编程角度来看,可以把文件分成两类:
①文本文件
②二进制文件
例如,要存储一个整数10000,就可以在磁盘上保存
文本文件:'1','0','0','0','0'
二进制文件: 10 27 00 00
区分的方法:如果使用记事本打开一个文件后,发现能看懂,就是文本文件,反之,就是二进制文件。(因为记事本是按照“文本文件”的方式来打开的)
五、如何在代码中对文件进行操作
5.1 打开文件 fopen
第一个参数为文件名,第二个参数表示打开方式,包含的头文件为:#include<stdio.h>。
对于第二个参数的理解:
1)针对“文本文件”进行操作
r: read ,只读;为了输入数据,打开一个已经存在的文本文件。
w: write,只写;为了输出数据,打开一个文本文件,如果文本文件不存在则创建该文件。
a: append,追加写;向文本文件尾添加数据
r+:读写;为了读和写,打开一个文本文件
w+:读写;为了读和写,建议一个新的文件
a+:读写;打开一个文件,在文件尾进行读写
2)针对二进制文件操作
rb: 只读;为了输入数据,打开一个二进制文件
wb:只写;为了输出数据,打开一个二进制文件,如果二进制文件不存在则创建该文件。
ab:追加;向一个二进制文件尾添加数据
rb+:读写;为了读和写打开一个二进制文件
wb+:读写;为了读和写,新建一个新的二进制文件
ab+:读写;打开一个二进制文件,在文件尾进行读和写
3)注意
①若"w","wb","w+","a+","wb+","ab+"指定文件不存在时,会建立一个新的文件,其它的会出错;
②打开文件对应就要关闭文件,关于关闭文件下面再做介绍。
5.2 读写文件
5.2.1 文件的顺序读写:
fgetc:字符输入函数;适用于所有输入流;
fputc:字符输出函数;适用于所有输出流
fgets:文本行输入函数;适用于所有输入流;
fputs:文本行输出函数;适用于所有输出流
fscanf:格式化输入函数;适用于所有输入流
fprintf:格式化输出函数;适用于所有输出流
fread:二进制输入;适用于文件
fwrite:二进制输出;适用于文件
例如:
#include<stdio.h> #include<stdlib.h> int main() { FILE* pfile; pfile = fopen("haha.txt", "w"); if (pfile != NULL){ fputs("fopen example", pfile); fclose(pfile); } return 0; }
由于haha.txt不存在,但是fopen的参数为"w",所以会创建该文件,通过fputs向文件中写入"fopen example",fopen打开文件就需要对应fclose关闭文件,最终我们能看到电脑上多出一个名为haha.txt的文件,打开后如下图所示:
5.2.2 文件的随机读写
①fseek:可以理解成,修改“光标”(cursor)的位置
第一个参数stream为文件指针;
第二个参数offset为偏移量,正数表示正向偏移,负数表示负向偏移;
第三个参数origin设定从文件的哪里开始偏移,可能取值为:SEEK_SET(文件开头)、SEEK_CUR(当前位置)或SEEK_END (文件末尾);
例如:
#include<stdio.h> int main() { FILE* pfile; pfile = fopen("example.txt", "wb"); fputs("This is an apple.", pfile); fseek(pfile, 9, SEEK_SET); fputs("sam", pfile); fclose(pfile); return 0; }
②ftell:返回文件指针相对于起始位置的偏移量
③rewind:让文件指针的位置回到文件的起始位置
5.3关闭文件 fclose
上面也提到过了,关闭文件的函数为fclose,它的原型如下
六、文件结束判定
在文件读取过程中,不能用feof函数的返回值直接用来判断文件的是否结束,而是当文件读取结束时,判断是读取失败结束,还是遇到文件尾结束。
6.1 文本文件读取是否结束,判断返回值是否为EOF(fgetc),或者NULL(fgets)
fgetc 判断是否为EOF,返回-1 EOF EOF end of file
fgets 判断返回值是否为NULL,返回NULL读取完毕了.
6.2二进制文件的读取结束判断,判断返回值是否小于实际要读的个数
判定文件读取完毕,取决于使用哪个函数在读。
如果是使用fread,返回值表示实际读到的元素个数n,第三个参数表示预期要读的元素个数count。如果n<count,就认为读完了,如果文件没读完,一定是n==count相等的。
理解如下:假设文件有110个元素,每个元素是一个char(1个字节)fread读的时候,count设为20。
第一次:n=>20,读到20个字节
第二次:n=>20,读到[20,40)个字节
第三次:n=>20,读到[40,60)个字节
第四次:n=>20,读到[60,80)个字节
第五次:n=>20,读到[80,100)个字节
第六次:n=>10,读到[100,110)个字节
七、文件缓冲区
目的是为了提高读写文件的效率
核心原理:访问内存的效率远远高于访问外存。
八、补充
1)所谓的“打印到控制台”更严谨的叫法,把数据写入到“标准输出”,标准输出就是操作系统中的一个特殊文件。操作系统中的重要思想:“一切皆文件”,操作系统需要管理很多软件资源和硬件设备,为了方便管理,操作系统把这些东西都抽象成“文件”来表示。
2)C的标准库和一些系统函数中,很多函数在执行出错的时候都会把出错的信息设置到errno这个错误码中,然后就可以通过这个错误码来识别出出错的原因。如果程序是对的,此时errno默认是0,如果要是非0,说明上个操作出错。
strerror:把错误码(errno)转成对应的文字解释
3)一个程序在启动的时候,自己默认打开了三个文件(标准输入stdin,标准输出stdout,标准错误stderr)