个人主页: 流年如夢
专栏: 《C语言》
文章目录
- 一.了解文件
- 1.1为什么需要使用文件
- 1.2什么是文件
- 二.二进制文件和文本文件
- 2.1文本文件
- 2.2二进制文件
- 三.文件的打开(fpoen)和关闭(fclose)
- 3.1流和标准流
- 3.2文件指针
- 3.3fopen --> 打开文件
- 3.4fclose -- > 关闭文件
- 3.5举例
- 四.文件的顺序读写([cplusplus链接](https://legacy.cplusplus.com/)👈)
- 表格
- 4.1fputc与fgetc
- 4.1.1函数原型
- 4.1.2举例
- 4.2fputs与fgets
- 4.2.1函数原型
- 4.2.2举例
- 4.3fprintf与fscanf
- 4.3.1函数原型
- 4.3.2举例
- 4.4fwrite与fread
- 4.41函数原型
- 4.4.2举例
- 4.5三组函数对比
- 五.文件的随机读写
- 5.1fseek --> 定位文件指针
- 5.2ftell --> 获取当前偏移
- 5.3rewind --> 回到文件开头
- 六.文件读取结束的判定(feof与ferror)
- 6.1feof
- 6.2ferror
- 七.文件缓冲区
- 八.更新文件(r+、w+、a+)
- 🎯总结
- ⚠️易错点
Ladies and gentlemen,本篇文章讲的是文件操作,下面将带领大家学习文件打开关闭(fopen、fclose)、顺序读写、随机读写、结束判定、文件缓冲区、更新文件等;全程高能,不容错过!!!
前言 程序运行时的数据都存放在内存中,程序退出后数据就会丢失。如果想让数据持久化保存,就必须用到文件操作。C语言提供了完整的文件读写接口,支持文本和二进制两种存储格式,能实现数据的写入、读取、修改、追加等功能。本篇文章带你从零掌握文件操作,写出稳定、安全、规范的文件处理代码。
一.了解文件
1.1为什么需要使用文件
因为程序退出后,内存数据会被回收,数据无法保存;但使用文件可以把数据存放在硬盘中,实现数据持久化;在下次运行程序时,可以从文件中读取历史数据。
1.2什么是文件
磁盘上的文件就是文件,例如我们电脑都有的C盘和D盘
当然,在程序设计中分为两类:程序文件和数据文件
程序文件:
- 源文件(
.c)- 目标文件(
.obj)- 可执行程序(
.exe)
数据文件(本篇重点):
程序运行时用于读写数据的文件
文件名:
文件名 =文件路径 + 文件名主干 + 后缀
例如:c:\code\test.txt二.二进制文件和文本文件
2.1文本文件
以ASCII字符形式存储,可以直接看懂的
2.2二进制文件
以内存二进制形式存储,节省空间、读写快
举个例子:
#include<stdio.h>intmain(){inta=10000;FILE*pf=fopen("test.txt","wb");fwrite(&a,4,1,pf);fclose(pf);pf=NULL;return0;}分析:wb是以二进制只写方式打开;fwrite是按二进制写入,int只占4字节
运行结果:
在这里程序没有报错,说明运行成功;这时双击左上角打开文件test.txt(或ctrl+c),我们可以看到10000以二进制方式写入文件,如下所示:
三.文件的打开(fpoen)和关闭(fclose)
3.1流和标准流
流(stream):数据传输的抽象,可理解为 “数据的河流”
三个默认标准流:
stdin--> 标准输入(用键盘)stdout--> 标准输出(在屏幕上)stderr--> 标准错误
3.2文件指针
每个打开的文件,系统都会创建一个FILE结构体信息区,我们用FILE*指针来操作文件
3.3fopen --> 打开文件
函数原型:
FILE*fopen(constchar*filename,constchar*mode);其中打开失败返回NULL,必须判断;mode是打开方式(例如r、w、a、rb、wb、ab、r+、w+、a+…)
3.4fclose – > 关闭文件
函数原型:
intfclose(FILE*stream);使用fclose关闭文件,并刷新缓冲区;关闭后必须把指针置 NULL
3.5举例
#include<stdio.h>intmain(){FILE*fp=fopen("test.txt","r");//这里先打开文件if(fp==NULL){perror("fopen");return1;}// 读写操作...fclose(fp);//最后关闭文件fp=NULL;return0;}🧐分析:先打开判断、用完关闭、最后指针置空;perror是用来直接打印错误原因,方便调试
四.文件的顺序读写(cplusplus链接👈)
表格
| 函数 | 功能 | 适用 |
|---|---|---|
| fputc | 写一个字符 | 所有输出流 |
| fgetc | 读一个字符 | 所有输入流 |
| fputs | 写一行字符串 | 所有输出流 |
| fgets | 读一行字符串 | 所有输入流 |
| fprintf | 格式化写入 | 所有输出流 |
| fscanf | 格式化读取 | 所有输入流 |
| fwrite | 二进制块写入 | 文件流 |
| fread | 二进制块读取 | 文件流 |
4.1fputc与fgetc
4.1.1函数原型
功能:向指定流中写入一个字符,写完后文件指针自动后移
参数:character是要写入的字符;stream是目标文件流
返回值:成功返回写入的字符,失败返回EOF
功能:从指定流中读取一个字符,读完后文件指针自动后移
参数:stream是要读取的文件流
返回值:成功返回读到的字符,读到末尾或出错返回EOF
4.1.2举例
//写入fputc('a',fp);//读取intch=fgetc(fp);4.2fputs与fgets
4.2.1函数原型
功能:向文件中写入一个字符串,不写入末尾
\0
参数:str是要写入的字符串;stream是目标文件流
返回值:成功返回非负数,失败返回EOF
功能:从文件中读取一行或指定长度字符串
参数:str是存放读取内容;num是最多读num-1个字符;stream是文件流
返回值:成功返回str,失败或到末尾返回NULL
4.2.2举例
fputs("hello world",fp);charbuf[100]={0};fgets(buf,100,fp);4.3fprintf与fscanf
4.3.1函数原型
功能:格式化写入文件,用法和
printf几乎一样
参数:stream是目标流;format是格式化字符串;后续为输出参数
返回值:成功返回写入字符数,失败返回负数
功能:格式化读取文件内容,用法和
scanf类似
参数:stream是输入流;format是格式串;后续为地址参数
返回值:成功返回读取参数个数,失败或到末尾返回EOF
4.3.2举例
structStu{charname[20];intage;};//写入fprintf(fp,"%s %d",s.name,s.age);//读取fscanf(fp,"%s %d",s.name,&s.age);//数组name本身就是指针,不需要 &4.4fwrite与fread
4.41函数原型
功能:以二进制形式整块写入文件
参数:ptr是数据地址;size是一个元素大小;count是元素个数;stream是文件流
返回值:成功写入的元素个数
功能:以二进制形式从文件整块读取数据
参数:ptr是接收数据的缓冲区;size是一个元素大小;count是要读个数;stream是文件流
返回值:实际读到的元素个数
4.4.2举例
//写入fwrite(&s,sizeof(structStu),1,fp);//读取fread(&s,sizeof(structStu),1,fp);4.5三组函数对比
| 函数 | 功能 |
|---|---|
| scanf | 从标准输入读 |
| fscanf | 从任意流读 |
| sscanf | 从字符串读 |
| printf | 打印到标准输出 |
| fprintf | 打印到任意流 |
| sprintf | 打印到字符串 |
五.文件的随机读写
5.1fseek --> 定位文件指针
函数原型:
SEEK_SET --> 文件开头
SEEK_CUR --> 当前位置
SEEK_END --> 文件末尾
例如:
fseek(fp,offset,origin);5.2ftell --> 获取当前偏移
函数原型:
功能:返回当前文件指针相对于开头的偏移量
例如:
longpos=ftell(fp);5.3rewind --> 回到文件开头
函数原型:
功能:把文件指针重置到文件开头
例如:
rewind(fp);六.文件读取结束的判定(feof与ferror)
6.1feof
判断是否是正常读到文件末尾
if(feof(fp))printf("读到文件末尾\n");6.2ferror
判断是否是发生读取错误
if(ferror(fp))printf("读取出错\n");注意:feof不是用来判断是否结束,而是结束后判断是 “读到尾” 还是 “出错”
七.文件缓冲区
系统会为每个文件自动开辟缓冲区;数据先写缓冲区,满了或刷新才写入磁盘;fflush(fp)会强制刷新缓冲区
fputs("abc",fp);fflush(fp);//立即写入磁盘八.更新文件(r+、w+、a+)
| 模式 | 文件不存在 | 原有内容 | 指针位置 |
|---|---|---|---|
r+ | 打开失败 | 保留 | 开头 |
w+ | 创建新文件 | 清空 | 开头 |
a+ | 创建新文件 | 保留 | 末尾 |
规则:
写完读:必须
fflush或fseek
读完写:必须fseek或rewind
🎯总结
- 文件用于数据持久化,分为文本文件和二进制文件
- 操作流程为
fopen--> 读写 -->fclose--> 置空(NULL) - 打开文件必须判断是否为
NULL - 顺序读写有
fgetc、fputc、fgets、fputs、fprintf、fscanf - 二进制读写有
fread与fwrite - 随机读写:
fseek、ftell、rewind - 结束判定时要用
feof和ferror区分结束原因 - 缓冲区:
fflush强制刷新,fclose自动刷新 - 更新模式读写切换必须刷新或重定位
⚠️易错点
- 不判断
fopen返回值,直接使用空指针- 忘记
fclose,导致数据丢失、文件占用fclose后不置空,形成野指针- 混淆文本方式与二进制方式
fgets读取时包含\n,处理不当出错- 读写切换不刷新、不定位,导致读写异常
- 用
feof提前判断循环结束,逻辑错误