3.认识文件名
每一个文件都有自己的文件标识-即文件名,以便用户识别和引用
文件名包含3部分:文件路径+文件名主干+文件后缀
文件路径指的这个文件在你电脑的具体位置,
文件名主干一般就是具体描述这个文件的名字,
文件名主干取名规则: 不能出现> < " * / \ | : ? 这些字符,且最多有255个字符
文件后缀 表示的是这个文件的属性类型,如.txt表示这个文件是文本文件
三.文件的基本操作
基本操作包括 文件指针FILE*的概念 和在C语言中文件的打开和关闭操作fopen 和fclose函数
这些都是在stdio.h头文件中存在的类型和函数
1.文件指针是什么
缓冲文件系统中,关键的概念是“文件类型指针”,简称“文件指针”。
每个被使用的文件都在内存中开辟了一个相应的文件信息区,
用来存放文件的相关信息(如文件的名字,文件状态及文件当前的位置等)。
这些信息是保存在一个结构体变量中的。该结构体类型是有系统声明的,取名FILE
不同的C编译器的FILE类型包含的内容不完全相同,但是大同小异。
例如,VS2013编译环境提供的 stdio.h 头文件中有以下的文件类型申明:
struct \_iobuf
{
char \*_ptr;
int _cnt;
char \*_base;
int _flag;
int _file;
int _charbuf;
int _bufsiz;
char \*_tmpfname;
};
typedef struct \_iobuf FILE;
每当打开一个文件的时候,系统会根据文件的情况自动创建一个FILE结构的变量,并填充其中的信息,
使用者不必关心细节,一般都是通过一个FILE的指针来维护这个FILE结构的变量,这样使用起来更加方便
FILE \*pf;//定义一个 文件指针类型的变量pf
定义pf是一个指向FILE类型数据的指针变量。
可以使pf指向某个文件的文件信息区(是一个结构体变量)。
通过该文件信息区中的信息就能够访问该文件。
也就是说,通过文件指针变量能够找到与它关联的文件。
每一个文件类型的指针,指向对应的一个文件信息区,每个文件信息区里存放着对应文件的数据,而通过这个指针就可以访问这个文件信息区,给文件进行添加删除数据操作…
2.文件的打开和关闭
在我们操作文件前,应先打开对应的文件,在使用结束后需要关闭对应的文件.
ANSIC 规定使用fopen函数来打开文件,fclose来关闭文件.
//打开文件
FILE \* fopen ( const char \* filename, const char \* mode );
//关闭文件
int fclose ( FILE \* stream );
而用fopen打开文件后会返回指向该文件信息区的FILE类型指针
此时就可以定义FILE类型的变量接受对应的指针…
3.fopen–打开文件操作
调用fopen函数需要传两个参数,
第一个是一个字符串,字符串内容表示要打开的文件名,
这个文件名可以用绝对地址例如:c:\code\test.txt 表示的该文件绝对路径,直接精确定位文件位置然后打开文件
也可以是相对路径,例如:test.txt 则此时只会在源程序所在的目录下打开名为text.txt文件
, 第二个也是字符串类型数据,表示以什么方式打开文件
下面是对应的各种基本的文件使用方式 以及含义 和 未存在当前文件时的处理方法
文件使用方式 | 含义 | 如果指定文件不存在 |
---|---|---|
“r”(只读) | 为了输入数据,打开一个已经存在的文本文件 | 出错 |
“w”(只写) | 为了输出数据,打开一个文本文件 | 建立一个新文件 |
“a”(追加) | 向文本文件尾添加数据 | 建立一个新文件 |
“rb”(只读) | 为了输入数据,打开一个二进制文件 | 出错 |
“wb”(只写) | 为了输出数据,打开一个二进制文件 | 建立一个新文件 |
“ab”(追加) | 向一个二进制文件尾添加数据 | 出错 |
“r+”(读写) | 为了读和写,打开一个文本文件 | 出错 |
“w+”(读写) | 为了读和写,建议一个新的文件 | 建立一个新文件 |
“a+”(读写) | 打开一个文件,在文件尾进行读写 | 建立一个新文件 |
“rb+”(读写) | 为了读和写打开一个二进制文件 | 出错 |
“wb+”(读写) | 为了读和写,新建一个新的二进制文件 | 建立一个新文件 |
“ab+”(读写) | 打开一个二进制文件,在文件尾进行读和写 | 建立一个新文件 |
根据上面打开方式 拿"r" 只读"w"只写 "a"追加 三种打开方式做介绍
①."r"以只读方式打开指定文件
"r"表示以只读方式打开指定的文件,这种方式是用来从文件里读取数据的
此时会根据你写的第一个参数文件名字符串根据是绝对地址还是相对地址去查找文件.
此时有两种情况:
1.如果不存在对应的文件名,则会返回NULL,并且会有一个报错信息
2.如果存在对应的文件名,则会将对应这个文件打开一个文件信息区,文件信息区里包含了这个文件的所有信息,并且返回指向这个文件信息区的一个文件类型指针
#define \_CRT\_SECURE\_NO\_WARNINGS
#include<stdio.h>
int main()
{
FILE\* pf = fopen("test.txt", "r");
if (pf == NULL)
{
printf("当前目录下不存在此文件\n");
perror("fopen");
}
return 0;
}
可以看到这个源程序的目录下此时为存在test.txt这个文件,如果此时打开就会返回NULL指针 .此时再用perror这个打印错误信息的函数输出错误信息↓
此时我们可以先在源程序所在目录下手动创建一个test.txt文件看看效果
此时运行程序 没有显示错误信息表示当前pf指针变量里已不再是空指针 表示已经打开了指定的文件信息区…↓
②"w"以只写方式打开指定文件
"w"表示以只写方式打开指定文件,因为这种方式是用来写数据到文件的
此时有两种情况
如果存在对应的文件名,会将此文件删除,然后创建一个同名同类型的文件
如果不存在对应的文件名,会自动创建一个对应名称类型的文件
测试一下此时目录下没有对应文件名的文件会是什么情况
运行程序后发现,程序不会显示不存在此文件说明pf不是NULL,并且打开所在目录发现已经新建了一个test.txt文件↓↓
当向已有的test.txt文件里输入一些信息然后再运行程序看看什么情况
运行程序再点开test.txt文件后发现原来的数据已经消失,表示已经将原来的文件删除 新建了一个同样文件名类型的空文件
③ "a"以追加形式打开指定文件
"a"表示以追加形式打开指定文件,追加表示的是如果文件里有数据则可以在原有数据后面添加新数据 此时有两种情况:
1.不存在指定文件时,会新建一个文件,打开其文件信息区返回文件指针
2.存在指定文件时,直接打开对应文件的文件信息区返回文件指针
测试一下如果不存在指定文件名时的情况
发现此时已经新建了一个名为text.txt的文件
测试当往已有的text.txt文件里输入数据后再运行程序的情况
发现运行程序后,文件里的文本信息不会丢失,表示此时不会将这个文件删除直接使用这个文件↓↓↓
以上测试了"r"只读 "w"只写 "a"追加 形式打开文件的方式,具体使用什么方式打开文件要看使用场景,上面打开方式还有很多种文件方式都可以使用
4.fclose–关闭文件操作
此操作类似于动态内存管理里的free函数
当我们操作了一个文件后,需要用fclose文件关闭函数将文件信息区关闭,
否则程序在运行过程中此文件信息区一直被打开而不需要被使用会降低系统性能
#define \_CRT\_SECURE\_NO\_WARNINGS
#include<stdio.h>
int main()
{
FILE\* pf = fopen("test.txt", "a");
if (pf == NULL)
{
printf("当前目录下不存在此文件\n");
perror("fopen");
}
fclose(pf); //将pf文件指针指向的文件信息区关闭
pf = NULL; //将pf指针变量 里置为NULL
return 0;
}
四.文件的读写操作
读写操作包括了文件的顺序读写 和随机读写 以及各种常用的函数讲解
1.文件的顺序读写
文件顺序读写表示从文件信息区起始位置开始往文件信息区里读出或者写入数据
文件信息区起始地址就相当于是文件指针偏移量为0时所指向的位置
下面是各种常用的向文件信息区里输入或者输出数据的库函数功能 函数名和适用的流
功能 | 函数名 | 适用于 |
---|---|---|
字符输入函数 | fgetc | 所有输入流 |
字符输出函数 | fputc | 所有输出流 |
文本行输入函数 | fgets | 所有输入流 |
文本行输出函数 | fputs | 所有输出流 |
格式化输入函数 | fscanf | 所有输入流 |
格式化输出函数 | fprintf | 所有输出流 |
二进制输入 | fread | 文件 |
二进制输出 | fwrite | 文件 |
①.输入流和输出流的概念
输入输出流可以看做往从文件里读取数据的过程和将数据输出到文件的过程
流看作一个过程,也可以相当于一个通道
适用于所有输入流:表示任何文件或其他可以是输入数据的程序文件或磁盘文件都可以往程序里输入数据,拿文件和键盘来说 ,键盘相当于是标准输入流,所有输入流表示可以从文件里读取数据,也可以从键盘上读取数据
键盘实际也相当于是一个文件,文件名为stdin,在c程序使用时默认已经打开了此文件
适用于所有输出流:表示可以将数据输出到任何文件里或者可以保存数据的程序里, 拿普通文件和屏幕来说,屏幕也被称为标准输出流. 所有输出流表示可以将数据输出到文件,也可以输出到屏幕上
屏幕实际上也可以看成一个文件,文件名为stdout,在c程序打开时默认打开了屏幕文件
而在文章前部分提到了了stdin 和stdout和stderr ,stderr表示的是将错误信息输出到屏幕上 ,stdin stdou stderr都可以看做是程序一开始就已经默认打开的文件,都可以直接使用
适用于文件:一般表示只能将数据输出到普通文件上,常用于将数据以二进制形式输出到文件中,因为二进制形式是计算机读取的语言,所以不适用于所有输入输出流,一般保存在文件里,并且对于人来说可读性差.
②.fgetc和fputc字符输入输出函数
fgetc字符输入函数, 返回类型为int 形参类型为FILE*文件指针
表示从文件信息区里文件指针当前偏移量处读取一个字符将这个字符的ASCLL码返回,并将文件指针偏移量往后移动一位
如果未读取到字符则会返回EOF(一般值为-1)
fputc字符输出函数, 返回类型int 函数参数 int 和FILE*
表示将一个整数以ASCLL码字符形式输出到文件指针指向的文件信息区的当前偏移量处,返回值是输出的字符 如果输出发生了错误则会返回EOF
#define \_CRT\_SECURE\_NO\_WARNINGS
#include<stdio.h>
int main()
{
FILE\* pf = fopen("test.txt", "w");//以只写形式打开
if (pf == NULL)
{
printf("打开失败\n");
perror("fopen");
}
char c ;
int n=fputc('A', pf); // 将字符A输出到pf指向的文件信息区
if (n == EOF)
{
printf("输出字符失败\n");
}
fclose(pf); //将pf文件指针指向的文件信息区关闭
pf = NULL;
pf = fopen("test.txt", "r"); //以只读形式打开
if (pf == NULL)
{
printf("打开失败\n");
perror("fopen");
}
n=fgetc(pf);
if (n == EOF)
{
printf("读取字符失败\n");
}
else
{
printf("%c", n);
}
fclose(pf); //将pf文件指针指向的文件信息区关闭
pf = NULL; //将pf指针变量 里置为NULL
return 0;
}
上面是fputc和fgetc的测试代码,先以只写形式打开test.txt文件
往文件信息区里输入字符A,然后再关闭此文件信息区,再以只读形式打开test.txt文件 从文件信息区里读取第一个字符,则读取了前面输入的字符A
为什么要关闭文件再打开而不直接读取?
1.因为设置了是只写形式打开文件只能写不能读
2.fputc输出一个字符到文件信息区里此时文件指针偏移量会往后移动一个位置表示此时指向文件里面A字符后面的一个位置,此时直接读取是读取不到字符A的需要使用fewind函数重置文件偏移量或者重新打开文件刷新偏移量
③.fgets和fputs文本行输入输出函数
fgets第一个参数为数组名用来接受读取的字符的数组
第二个为要读取的字符串字符个数,
第三个为文件指针 表示从文件里读取num-1个字符
num是第二个参数,表示读取num-1个字符然后最后自动加上\0字符得到num个字符赋给第一个参数
在读取过程中如果遇到\n会读取掉\n然后直接结束 读最后将读取到的字符串最后加上\0放在指定数组中(数组容量要大)
读取成功会返回存放读取的字符串的字符指针,读取失败返回NULL
fputs文本行输出函数, 将字符串输出到文件指针指向的文件信息区,文件指针偏移量再往后移动输出的字符个数的大小
输出成功返回非负值,失败返回EOF
#define \_CRT\_SECURE\_NO\_WARNINGS
#include<stdio.h>
int main()
{
FILE\* pf = fopen("text.txt", "w");
if (pf == NULL)
{
perror("fopen");
}
else
{
int n=fputs("123\n456", pf); //将123456输出到pf指向的文件信息区
if (n == EOF) //如果返回值为EOF则表示输出失败
{
printf("输出失败\n");
}
else //否则输出成功
{
printf("输出成功\n");
}
fclose(pf); //使用完后将文件信息区关闭
pf = NULL;
}
pf = fopen("text.txt", "r");
if (pf == NULL)
{
perror("fopen");
}
else
{
char a[7];
char\* tmp = fgets(a, 6, pf); //从pf指向的文件信息区读取 3个字符后加上\0共4个字符如果中途遇到\n则会直接读取\n后结束读取将读取的字符串在最后加上\n然后 存放在a数组中
if (tmp == NULL)
{
printf("读取信息失败\n");
}
else
{
printf("已读取信息:%s", a);
}
}
return 0;
}
④fscanf和fprintf格式化输入输出函数
这两个函数和scanf printf差不多 多的就是一个文件指针
fscanf 比scanf最左边多了个参数,表示文件指针,其它的参数和scanf一样,
表示从文件指针指向的文件信息区中读取对应格式的数据输入到对应的变量里
最后返回的值是赋值的变量个数,未分配则返回EOF
fprintf()函数根据指定的format(格式)(格式)发送信息(参数)到由stream(流)指定的文件. fprintf()只能和printf()一样工作. fprintf()的返回值是输出的字符数,发生错误时返回一个负值.
表示将对应变量里的值以对应格式输出到文件指针指向的信息区内,最后返回输出的字符个数,发生错误则返回复制
#define \_CRT\_SECURE\_NO\_WARNINGS
#include<stdio.h>
int main()
{
FILE\* pf = fopen("text.txt", "w");
if (pf == NULL)
{
perror("fopen");
}
else
{
int n=fprintf(pf, "%s", "Hello World");
if (n < 0)
{
printf("输出失败\n");
}
else
{
printf("输出成功\n");
}
fclose(pf);
pf = NULL;
}
pf = fopen("text.txt", "r");
if (pf == NULL)
{
perror("fopen");
}
else
{
char arr[20];
fscanf(pf, "%s", arr); //和scanf读取效果一样 遇到间隔符后结束读取 偏移量移到读取结束的位置
printf("读取的内容为:%s\n", arr); // 读取到Hello 遇到空格结束将读取到的字符给arr
fscanf(pf, "%s\n", arr); //从空格位置开始读取跳过空格将后面的World读取到末尾结束将字符串给arr
printf("读取的内容为:%s\n", arr);
}
return 0;
}
⑤.fread和fwrite二进制输入输出函数
fread和fwrite 都是以二进制形式输入输出,输入到文件里显示的数据是二进制形式,具有一定的数据安全功能,因为很多人是读不懂二进制数的
函数fread()读取[num]个对象(每个对象大小为size(大小)指定的字节数),并把它们替换到由buffer(缓冲区)指定的数组. 数据来自给出的输入流. 函数的返回值是读取的内容数量…
使用feof()或ferror()判断到底发生哪个错误
fwrite()函数从数组buffer(缓冲区)中, 写count个大小为size(大小)的对象到stream(流)指定的流. 返回值是已写的对象的数量.
#define \_CRT\_SECURE\_NO\_WARNINGS
#include<stdio.h>
int main()
{
FILE\* pf = fopen("text.txt", "wb"); //以二进制只写形式打开文件
if (pf == NULL)
{
perror("fopen");
}
else
{
int a=666666;
int n=fwrite(&a, sizeof(a), 1, pf); //从 a里 读取1 个 sizeof(a)大小 的数据转换为二进制形式输出到pf指向的文件信息区中
if (n != 1)
{
printf("输出失败\n");
}
else
{
printf("输出成功\n");
![img](https://img-blog.csdnimg.cn/img_convert/b7a28c702a4dfa0eaaca6c744e2eca5a.png)
![img](https://img-blog.csdnimg.cn/img_convert/a4d1b39b654597050b3808079ee47b3a.png)
![img](https://img-blog.csdnimg.cn/img_convert/7cf30a915dabe563b9b2b2d36d2fc8fd.png)
**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上大数据知识点,真正体系化!**
**由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新**
**[需要这份系统化资料的朋友,可以戳这里获取](https://bbs.csdn.net/topics/618545628)**
)中, 写count个大小为size(大小)的对象到stream(流)指定的流. 返回值是已写的对象的数量.
>
>
>
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
int main()
{
FILE* pf = fopen(“text.txt”, “wb”); //以二进制只写形式打开文件
if (pf == NULL)
{
perror(“fopen”);
}
else
{
int a=666666;
int n=fwrite(&a, sizeof(a), 1, pf); //从 a里 读取1 个 sizeof(a)大小 的数据转换为二进制形式输出到pf指向的文件信息区中
if (n != 1)
{
printf(“输出失败\n”);
}
else
{
printf(“输出成功\n”);
[外链图片转存中…(img-ar1jRciW-1714547953558)]
[外链图片转存中…(img-F6INVNdN-1714547953558)]
[外链图片转存中…(img-LFMEMIHX-1714547953558)]
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上大数据知识点,真正体系化!
由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新