【C语言】文件操作详解

这篇博客适合初学者,详细介绍了C语言中的文件操作,包括文件的用途、类型、打开与关闭、顺序读写、随机读写、文本与二进制文件的区别,以及文件读取结束的判定。通过实例代码演示了fopen、fclose、fgetc、fgets等函数的使用,帮助理解文件操作的基本流程。
摘要由CSDN通过智能技术生成

✨ 写在前面

🎃 哈喽 大家好👋👋👋
🌱 作为一个初入编程的大学生,知识浅薄,但还是要学习大佬写一下前言滴(🤭)
🌱 我的其他文章
       1.【C语言】字符串函数使用+模拟【上】
       2.【C语言】彻底搞明白C语言一大关卡—C指针【初阶】
       3.【C语言】字符串操作函数&&字符串查找&&内存操作函数【下】

🌱 初入编程的世界 前方"路漫漫"🛣️ 每天我们都要进步一点点💧
🌱 希望分享知识的同时可以和你们一起进步🍻

✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨✨

目录

🐼1.为什么使用文件

🐼2.什么是文件

🐻‍❄️2.1 程序文件

🐻‍❄️2.2 数据文件

🐻‍❄️2.3 文件名

🐼3.文件的打开和关闭

🐻‍❄️3.1 文件指针

🐻‍❄️3.2 文件的打开和关闭

!!注意:

🐼4.文件的顺序读写

🐨 fgetc&&fputc

🐨 fgets&&fputs

🐨 二进制形式写入和读取 

🐻‍❄️4.1 对比一组函数

🐨4.1.1 fscanf && fprintf

🐼5.文件的随机读写

🐻‍❄️5.1 fseek函数

🐻‍❄️5.2 ftell

🐻‍❄️5.3 rewind

🐼6.文本文件和二进制文件

🐼7.文件读取结束的判定

🐻‍❄️7.1 被错误使用的feof

🐼8.文件缓冲区

⭐文件操作学生成绩涨十分


🐼1.为什么使用文件

有时候我们写的程序 是需要保存起来的 

比如说写一个通讯录 我们存入的联系人需要保存起来,否则退出程序输入的数据就自动销毁了

这样每一次运行程序 都要重新录入数据

所以如果想把数据持久化,一般有两个方法

  1. 存放在电脑磁盘
  2. 存放到数据库

我们使用文件的时候 是存放在电脑磁盘中的

🐼2.什么是文件

我们知道 磁盘上的文件叫做文件

但是对于程序设计中,从文件的功能来分类,一般谈的文件有两种:程序文件数据文件

🐻‍❄️2.1 程序文件

包括

源文件(后缀.c)

目标文件(后缀:windows下.obj,Linux环境下.o)

可执行文件(后缀.exe)

🐻‍❄️2.2 数据文件

文件的内容不一定是程序,而是程序运行需要从中数据的文件,或者输出内容的文件

我们讨论的是数据文件

之前我们所处理的数据的输入和输出 都是从键盘输入 屏幕输出

我们现在要考虑的是 数据输入到文件中,或者从文件读取输出到屏幕

🐻‍❄️2.3 文件名

一个文件要有一个唯一的文件标识,以便用户识别和引用

文件名包含三部分:文件路径 + 文件名主干 + 文件后缀

 例如:c:\code\test.txt

为了方便起见,文件标识常被称为 文件名

一个易错点

         文件名中一定包含后缀名:

扩展名并非必须,而仅仅是一个提示,提示该文件最可能由何种应用程序打开,或者如何处理。

🐼3.文件的打开和关闭

🐻‍❄️3.1 文件指针

缓冲文件系统中,关键的概念是 “文件类型指针”,简称”文件指针

每一个被使用的文件都在内存中开辟了一个相应的文件信息区,用来存放文件的相关信息(例如文件的名字,文件状态以及文件当前的位置),这些信息是保存在一个结构体变量中的。该结构体类型是有声明的,取名为 FILE

 例如这个文件类型的声明:

struct _iobuf {
    char *_ptr;
    int  _cnt;
    char *_base;
    int  _flag;
    int  _file;
    int  _charbuf;
    int  _bufsiz;
    char *_tmpfname;
   };
typedef struct _iobuf FILE;

 该声明中包含了文件的各种信息

不同的C编译器的FILE类型包含的内容不完全相同,但是大同小异

每次打开一个文件,操作系统会根据文件的情况自动创建一个FILE结构的变量,并自动填充里面的信息,我们不用关心那些细节

而我们如果想对文件中的内容进行操作 一般通过一个FILE* 的指针 来访问该结构体

FILE * pf;//文件指针变量

 定义pf是一个指向FILE类型数据的指针变量。可以使pf指向某个文件的文件信息区(是一个结构体变量)。通过该文件信息区中的信息就能够访问该文件。也就是说,通过文件指针变量能够找到与他相关联的文件

就像这样:

🐻‍❄️3.2 文件的打开和关闭

对文件进行读写之前,应该先打开文件,使用结束后应关闭该文件,并把指针置空

在编写程序的时候,再打开文件的同时,都会返回一个FILE*的指针变量指向该文件,也相当于建立了指针和文件的关系

标准C 规定:fopen---打开文件

                      fclose---关闭文件

//打开文件
FILE* pf = fopen(const char* filename, const char* mode);
//关闭文件
int flose(FILE* stream);

 fopen() 函数第一个参数是文件名的地址(字符串),第二个参数是文件的打开方式(也是字符串)

fclose() 函数只有一个参数  就是文件指针


 文件的打开方式:

文件使用方式含义如果指定文件不存在
"r"(只读)为了输入数据,打开一个已经存在的文本文件出错
"w"(只写)        为了输出数据,打开一个文本文件     建立一个新的文件
"a"(追加)向文本文件尾添加数据                        建立一个新的文件
“rb”(只读)为了输入数据,打开一个二进制文件     出错
“wb"(只写)为了输出数据,打开一个二进制文件建立一个新的文件
“ab”(追加)向一个二进制文件尾添加数据出错
“r+”(读写)为了读和写,打开一个文本文件出错
“w+”(读写)为了读和写,建议一个新的文件建立一个新的文件
“a+”(读写)打开一个文件,在文件尾进行读写建立一个新的文件
“rb+”(读写)为了读和写打开一个二进制文件 出错
“wb+”(读写)为了读和写,新建一个新的二进制文件建立一个新的文件
“ab+”(读写打开一个二进制文件,在文件尾进行读和写建立一个新的文件

其中最常用的 是 “r”,“w”,“a” 

r---只读 从一个已经存在的文件中进行读取

“w”---只写  如果文件存在则打开清空内容重新写(每一次写会刷新内容),如果文件不存在 新建立一个文件进行写

!!注意:

我们使用文件 一般都是 

1.打开文件(fopen) 并判断是否成功打开

2.读/写文件...一系列操作

3.关闭文件 (fclose)

🐼4.文件的顺序读写

文件的顺序读写函数

功能功能适用于
字符输入函数fgetc 所有输入流
字符输出函数fputc 所有输出流
文本行输入函数fgets 所有输入流
文本行输出函数fputs 所有输出流
格式化输入函数fscanf 所有输入流
格式化输出函数fprintf 所有输出流
二进制输入fread文件
二进制输出fwrite 文件

下面是使用的两个例子 

🐨 fgetc&&fputc

1.向文件中写入多个字符 并读出字符

 

 

可以看到 已经向文件 text.txt 写进入了 abcdef

接下里我们要 读出来 看一下 

 

可以看到 成功的输出到了屏幕

🐨 fgets&&fputs

2.向文件中写入一行 并读出一行

 

 

 输出效果:

 

 关于缓冲区的概念后面会有介绍

🐨 二进制形式写入和读取 

 

 const void* buffer ---->  指向需要写入的数据的指针

 void* buffer ----->存放数据的位置

 

 可以看到 用记事本打开 是读不出来的 因为是用二进制方式写入的

因此我们需要用二进制方式读取出来

 

可以看到 成功读取了文件数据

🐻‍❄️4.1 对比一组函数

在对比之前 我们先普及一个知识

我们经常在使用的 printf函数  scanf函数

是针对于 标准输出流 (屏幕 标准输入流 (键盘

 这里我们对比一下 三组函数

  1. scanf   /  printf
  2. fscanf  /  fprintf
  3. sscanf  /  sprintf

scanf / printf -----> 针对标准输出/输入流

fscanf / fprintf ----->针对 所有输出/输入流

sscanf / sprintf ------>针对 字符串的输入输出

 下面是 使用的例子:

🐨4.1.1 fscanf && fprintf

 调用test_struct_1

 

fscanf fprintf 相比于scanf 和 printf 

只是前面多了一个 FILE* pf --->从文件中读取或者输出到文件

🐼5.文件的随机读写

🐻‍❄️5.1 fseek函数

fseek 这家伙的作用 就是根据文件指针的位置和偏移量来定位文件指针

注意:只是定位 --->让指针指向你想指向的那个位置

 

 参数 1:文件指针

参数2:要设置的偏移量

参数3:起始位置(偏移量的参考位置--也就是偏移量为0)

 注意:

第三个位置是标准给定的三个选择

 SEEK_CUR----->现在的位置

SEEK_END ----->文件末尾

SEEK_SET ----> 文件开头

来看一下使用例子:

 首先向text.txt文件中输出“hello world”

 然后打开文件(只读)利用fseek进行操作

具体细节 看注释呀 (这里平时用的比较少)

 

🐻‍❄️5.2 ftell

返回文件指针相对于起始位置的偏移量

 

 

可以发现文件被改了 

 

 把b位置改为w之后 指针自动向后+1 所以现在文件指针指向c  相对于起始位置 偏移量为2

🐻‍❄️5.3 rewind

由于文件读写过程中 文件指针指向的位置不免会发生变化

rewind的作用就是 让文件指针的位置 回到文件的起始位置

文件的起始位置 默认为SEEK_SET

🐼6.文本文件和二进制文件

根据数据的组织形式,数据文件被称为文本文件或者二进制文件。
数据在内存中以二进制的形式存储,如果不加转换的输出到外存,就是二进制文件。
如果要求在外存上以ASCII码的形式存储,则需要在存储前转换。以ASCII字符的形式存储的文件就是文
本文件。
一个数据在内存中是怎么存储的呢?
字符一律以ASCII形式存储,数值型数据既可以用ASCII形式存储,也可以使用二进制形式存储。
如有整数10000,如果以ASCII码的形式输出到磁盘,则磁盘中占用5个字节(每个字符一个字节),而
二进制形式输出,则在磁盘上只占4个字节

 例如 我们以二进制形式把10000放入文件 

 

我们在记事本中是看不到的  那么如何才可以看得到?

 

 

可以看到 其存储形式 其实就是 10000转换为二进制 然后 以十六进制形式存储

 总结:如下图

🐼7.文件读取结束的判定

🐻‍❄️7.1 被错误使用的feof

牢记:在文件读取过程中,不能用feof函数的返回值直接用来判断文件的是否结束。
而是应用于当文件读取结束的时候,判断是读取失败结束,还是遇到文件尾结束。
1. 文本文件读取是否结束,判断返回值是否为 EOF ( fgetc ),或者 NULL ( fgets )
例如:
fgetc 判断是否为 EOF .
fgets 判断返回值是否为 NULL .
2. 二进制文件的读取结束判断,判断返回值是否小于实际要读的个数。
例如:
fread判断返回值是否小于实际要读的个数。

 所以 feof 的使用场景 就是 当文件读取结束 先用ferror函数判断是不是因为 读取失败而失败的

再用feof 判断是不是因为读取到文件尾而结束的

 可以看到 我们打开一个不存在的文件夹:提示 没有这样的文件!!

🐼8.文件缓冲区

事实上,我们写好程序 进行读取文件的时候,并不是一次一次 向文件中找数据的!!!

否则 每一次读取都要向操作系统申请指令 ,这无疑打乱了操作系统正常的运作

操作系统内心一万个不愿意(一点点小事就来找我 一点点小事就来找我 好烦呀)

所以 就有了一个缓冲区的概念 

当输出数据的时候 先输出到缓冲区 当缓冲区满了,就会放入到硬盘

同理 输入数据的时候  文件中的数据 先输入到缓冲区 然后在输出到程序

(相当于 先攒够一定的问题再去问老师)

 而缓冲区什么时候满呢?---->  缓冲区的刷新

注意: fclose(FILE* filename) 的另一个作用就是 刷新缓冲区 (也就是把缓冲区的数据保存到硬盘)

            另一个方法 : 主动刷新缓冲区:fflush(FILE* filename)函数 

当然 这里我们使用的比较少,了解一下就可以

总结一下:

因为有缓冲区的存在,C语言在操作文件的时候,需要做刷新缓冲区或者在文件操作结束的时候关闭文件。
如果不做,可能导致读写文件的问题。 

⭐文件操作学生成绩涨十分

  1. 首先准备一个记事本 存放10个学生成绩 

 

2. 直接代码 (相信看了这篇文章 你能够自己实现哦)

 3.看一下效果

 ⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐

❤️❤️❤️😚😚😚 感谢阅读😗😗😗❤️❤️❤️

  • 9
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

2021狮子歌歌

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值