c语言文件操作详解:fgetc,fputc,fgets,fputs,fscanf,,fprintf,fread,fwrite的使用和区别
前言:在对于c语言的学习中,我们为了持续使用一些数据,为了让我们的数据可以在程序退出后仍然保存并且可以使用,我们引入了文件的概念和操作,本文旨在为大家分享在文件操作中常用的输入输出函数的使用方式和技巧,以及分析它们之间的区别
目录
一.常用文件顺序读写函数
二.字符操作函数 fgetc 和 fputc
fgetc
fputc
三.文本行操作函数 fgets 和 fputs
fgets
fputs
四.格式化操作函数 fscanf 和 fprintf
fscanf
fprintf
五.二进制操作函数
fread
fwrite
解密二进制文件
总结与分析
一.常用文件顺序读写函数
在这里我们先给出本次分享要讲解的函数的大致声明列举
功能 | 函数名 | 适用于 |
字符输入函数 | fgetc | 所有输入流 |
字符输出函数 | fputc | 所有输出流 |
文本行输入函数 | fgets | 所有输入流 |
文本行输出函数 | fputs | 所有输出流 |
格式化输入函数 | fscanf | 所有输入流 |
格式化输出函数 | fprintf | 所有输出流 |
二进制输入 | fread | 文件 |
二进制输出 | fwrite | 文件 |
二.字符操作函数 fgetc 和 fputc
我们还是给出 cplusplus 官网的讲解说明:
fgetc:fgetc - C++ Reference (cplusplus.com)
fputc:fputc - C++ Reference (cplusplus.com)
fgetc
我们先来观察 fgetc 函数, 官方文本显示如下:
- 从流中获取字符
- 返回指定流的内部文件位置指示符当前指向的字符。然后将内部文件位置指示符推进到下一个字符
- 如果流在被调用时位于文件的末尾,则该函数返回 EOF 并为流设置文件结束指示器(feof)
- 如果发生读错误,该函数返回EOF并设置流的错误指示器(error)
- Fgetc 和 getc 是等价的,除了 getc 可以在某些库中作为宏实现
为了更加具体的理解,我们写出一个文件
然后我们对其进行输入
在确保了我们的文件可以有内容读取后,我们编程实现观察结果,我们以读取的方式打开文件,然后使用 ch 变量挨个读取文件中的字符并且打印
int main()
{//打开文件FILE* pf = fopen("data.txt", "r");if (pf == NULL){perror("fopen");return 1;}//读文件int ch = fgetc(pf);printf("%c", ch);ch = fgetc(pf);printf("%c", ch);ch = fgetc(pf);printf("%c", ch);ch = fgetc(pf);printf("%c", ch);ch = fgetc(pf);printf("%c", ch);//关闭文件fclose(pf);pf = NULL;return 0;
}
然后我们可以发现,确实可以读取到文件中的字符
- 综合上述操作,我们可以得出结论,fgetc 函数可以挨个读取文件中的字符,我们可以定义一个变量来接收 fgets 的返回值(字符的ASCII码)然后进行输出等操作
- 在使用该函数的时候,我们只需要将文件指针(流)作为参数传给函数,然后我们就可以得到一个字符的ASCII码
fputc
我们先来观察 fputc 函数, 官方文本显示如下:
- 将字符写入流
- 将一个字符写入流并推进位置指示器
- 字符被写入流的内部位置指示器所指示的位置,然后自动向前移动一个
我们还是用代码示例来演示,这样更方便我们理解
在演示前,我们确保文件内是空白的
int main()
{//打开文件FILE* pf = fopen("data.txt", "w");if (pf == NULL){perror("fopen");return 1;}//写文件fputc('a', pf);fputc('b', pf);fputc('c', pf);fputc('d', pf);fputc('e', pf);//关闭文件fclose(pf);pf = NULL;return 0;
}
运行后:
我们可以发现,通过 fputc 函数挨个对文件输入了从 ‘a’ 到 ‘e’ 的字符
综合上述操作,我们可以得出结论,fputc 函数可以挨个字符的对文件进行写入的操作,函数内部需要注意的有俩个参数
- 要写入的字符
- 要写入文件的文件指针(流)
三.文本行操作函数 fgets 和 fputs
我们还是给出 cplusplus 官网的讲解说明:
fgets:fgets - C++ Reference (cplusplus.com)
fputs:fputs - C++ Reference (cplusplus.com)
fgets
我们先来观察 fgets 函数, 官方文本显示如下:
- 从流中获取字符串
- 从流中读取字符,并将其作为C字符串存储到 str 中,直到读取 (num-1) 个字符,或者到达换行符或文件结束符,以先发生的为准
- 换行符使 fgets 停止读取,但它被函数认为是一个有效字符,并包含在复制到 str 的字符串中。
- 在复制到 str 的字符之后,将自动追加一个终止 null 字符。
- 请注意,fgets 与 gets 有很大的不同:fgets 不仅接受流参数,而且允许指定 str 的最大长度,并在字符串中包含任何结束换行符
我们还是用一段示例来理解,首先有个 data.txt 的文件如下
我们给出代码如下:
int main()
{//打开文件FILE* pf = fopen("data.txt", "r");if (pf == NULL){perror("fopen");return 1;}//读文件char arr[100] = {0};fgets(arr, 100, pf);printf("%s", arr);fgets(arr, 100, pf);printf("%s", arr);//关闭文件fclose(pf);pf = NULL;return 0;
}
输出结果:
根据输出结果,我们可以发现,一条 fgets 函数可以读取一行的内容,但是在使用的时候需要注意设置一个字符数组来接收字符串,函数在使用时,一共有三个参数
- 要传入数组的地址
- 要复制到字符串中的最大字符数
- 文件指针(流)
fputs
我们先来观察 fputs 函数, 官方文本显示如下:
- 将字符串写入流
- 将由 str 指向的C字符串写入流
- 函数从指定的地址 (str) 开始复制,直到到达结束的空字符 ('\0'),这个终止的空字符不会复制到流中
- 注意,fputs 与 puts 的不同之处不仅在于可以指定目标流,而且 fputs 不会写入额外的字符,而 puts 会自动在末尾附加一个换行符
我们还是用一段示例来理解,首先还是设定一个空白内容的 data.txt 的文件
我们给出代码如下:
int main()
{//打开文件FILE* pf = fopen("data.txt", "w");if (pf == NULL){perror("fopen");return 1;}//写文件char arr[] = "hello";fputs(arr, pf);fputs("world", pf);//关闭文件fclose(pf);pf = NULL;return 0;
}
运行结果:
根据运行结果,我们可以判断, fputs 函数一次性可以对文件写入一行字符串,只要声明字符串的内容或者地址,都可以进行写入,它的俩个参数分别如下:
- 要写入的字符串的内容或者地址
- 要写入的文件指针(流)
四.格式化操作函数 fscanf 和 fprintf
我们还是给出 cplusplus 官网的讲解说明:
fscanf:fscanf - C++ Reference (cplusplus.com)
fprintf:fprintf - C++ Reference (cplusplus.com)
fscanf
我们先来观察 fscanf 函数, 官方文本显示如下:
- 从流中读取格式化的数据
- 从流中读取数据,并根据参数格式将其存储到附加参数所指向的位置
- 额外的参数应该指向已经分配的对象,其类型由格式字符串中相应的格式说明符指定
我们还是用一段示例来理解,首先有个 data.txt 的文件如下
我们给出相对于的代码如下:
struct S
{float f;char c;int n;
};int main()
{struct S s = {0};//打开文件FILE* pf = fopen("data.txt", "r");if (pf == NULL){perror("fopen");return 1;}//读文件fscanf(pf, "%f-%c-%d", &(s.f), &(s.c), &(s.n));printf("%f-%c-%d\n", s.f, s.c, s.n);//关闭文件fclose(pf);pf = NULL;return 0;
}
输出结果:
根据输出结果,我们可以发现,原本文件中的字符串,被我们以 float char int 的格式分别读到了 f,c,n 三个变量中,也就是说我们将原本的字符串变成了不同格式的数据,在使用这个函数时,注意他的参数,只比 scanf 多了一个参数,也就是文件指针(流)
fprintf
我们先来观察 fprintf 函数, 官方文本显示如下:
- 将格式化的数据写入流
- 将由 format 指向的 C字符串写入流。如果 format 包含格式说明符(以%开头的子序列),则格式化format 之后的其他参数并将其插入到结果字符串中,以替换它们各自的说明符。
- 在format 形参之后,函数期望至少与format 指定的一样多的附加参数。
我们还是用一段示例来理解,首先有个 data.txt 的空文件
我们给出代码如下:
struct S
{float f;char c;int n;
};int main()
{struct S s = { 3.14f, 'w', 100 };//打开文件FILE* pf = fopen("data.txt", "w");if (pf == NULL){perror("fopen");return 1;}//写文件fprintf(pf, "%f-%c-%d", s.f, s.c, s.n);//关闭文件fclose(pf);pf = NULL;return 0;
}
运行结果:
根据输出结果,我们可以发现,我们以结构体的格式,将其中 float char int 三种类型的数据写入了文件,在写入文件后,这些数据就失去了原本的格式,相当于变成了一条字符串,在使用的时候,他只比我们的 scanf 多了一个参数,也就是文件指针(流)
五.二进制操作函数
我们还是给出 cplusplus 官网的讲解说明:
fread:fread - C++ Reference (cplusplus.com)
fwrite:fwrite - C++ Reference (cplusplus.com)
fread
我们先来观察 fread 函数, 官方文本显示如下:
- 从流中读取数据块
- 从流中读取一个由 count 元素组成的数组,每个元素的大小为 size 字节,并将它们存储在 ptr 指定的内存块中
- 流的位置指示器按读取的总字节数前进
- 如果成功读取的总字节数为 (size*count)
该函数一共有 4 个参数:
void * ptr:指向大小至少为(size*count)字节的内存块的指针,转换为 void*size_t size:要读取的每个元素的大小(以字节为单位)
size_t count:元素的数目,每个元素的大小为 size 字节
FILE * stream:指向指定输入流的 FILE 对象的指针(文件指针)
为了方便理解,我们还是用一段示例来理解,首先有个 data.txt 的文件如下
然后给出代码如下:
//二进制的方式读取文件
int main()
{int arr[10] = {0};//写文件FILE* pf = fopen("data.txt", "rb");if (pf == NULL){perror("fopen");return 1;}//二进制的读文件fread(arr, sizeof(arr[0]), sizeof(arr) / sizeof(arr[0]), pf);int i = 0;for (i = 0; i < 10; i++){printf("%d ", arr[i]);}//关闭文件fclose(pf);pf = NULL;return 0;
}
运行结果:
我们发现和我们预期的完全不一样,这是因为我们读取是以二进制的方式读取,打印的时候却是以十进制的方式打印,这样就相当于给数据加密了,我们无法直观的看见我们读取了什么数据,但是我们确确实实是读取到了
我们如何验证我们读到的数据就是我们想存储的那部分呢?后文在介绍fwrite的时候笔者会给大家进行验证
fwrite
我们先来观察 fwrite 函数, 官方文本显示如下:
- 将数据块写入流
- 将由 count 元素组成的数组 (每个元素的大小为 size 字节) 从 ptr 所指向的内存块写入流中的当前位置
- 流的位置指示器按写入的总字节数前进
- 在内部,该函数将 ptr 指向的块解释为 unsigned char 类型的 (size*count) 元素数组,并将它们顺序写入流,就像对每个字节调用 fputc 一样
它也有四个参数如下:
void * ptr:指向大小至少为(size*count)字节的内存块的指针,转换为 void*size_t size:要写入的每个元素的大小(以字节为单位)
size_t count:元素的数目,每个元素的大小为 size 字节
FILE * stream:指向指定输入流的 FILE 对象的指针(文件指针)
为了方便理解,我们还是用一段示例来理解,首先有个 data.txt 的空文件
然后我们给出代码如下:
//二进制的方式写进文件
int main()
{int arr[] = { 1,2,3,4,5,6,7,8,9,10 };//写文件FILE*pf = fopen("data.txt", "wb");if (pf == NULL){perror("fopen");return 1;}//二进制的写文件fwrite(arr, sizeof(arr[0]), sizeof(arr)/sizeof(arr[0]), pf);//关闭文件fclose(pf);pf = NULL;return 0;
}
运行结果:
同样,我们还是无法直观的看见我们存储了什么,这是因为记事本使用的是 UTF-8 码,和我们保存的二进制并不兼容,这从十进制转到二进制再用 UTF-8 码进行显示也就相当于对文本进行了一层加密
那如何验证数据的真实性呢?我们可以使用刚才介绍的 fread 进行读取,然后观察
解密二进制文件
这里生成的data.txt 的文件我们保持不动,我们使用刚才介绍的 fread 来读取这个文件
//二进制的方式读取文件
int main()
{int arr[10] = {0};//写文件FILE* pf = fopen("data.txt", "rb");if (pf == NULL){perror("fopen");return 1;}//二进制的读文件fread(arr, sizeof(arr[0]), sizeof(arr) / sizeof(arr[0]), pf);int i = 0;for (i = 0; i < 10; i++){printf("%d ", arr[i]);}//关闭文件fclose(pf);pf = NULL;return 0;
}
运行结果:
我们可以看见,我们第一次用fwrite写入的从 1到10 的数组被我们成功的读取到了,也就是说不管是 fread 还是fwrite
他们在对数据的写入和读出的时候麻豆不会影响数据的真实性,他们只是相当于对数据进行了加密,所以导致了我们无法直观的阅读数据
总结与分析
fgetc:从文件中读取单个字符
fputc:对文件写入单个字符
fgets:从文件中读取一个字符串
fputs:对文件写入一个字符串
fscanf:将文件中的字符串转换为有格式的数据并且读取出来
fprintf:将有格式的数据转换为字符串并且写入文件
fread:将文件中的内容转换为二进制然后读取出来
fwrite:将数据转换为二进制然后写入文件
本次的分享就到此为止了,感谢您的支持,如果您也不同的见解,欢迎积极提出交流
相关文章:

c语言文件操作详解:fgetc,fputc,fgets,fputs,fscanf,,fprintf,fread,fwrite的使用和区别
前言:在对于c语言的学习中,我们为了持续使用一些数据,为了让我们的数据可以在程序退出后仍然保存并且可以使用,我们引入了文件的概念和操作,本文旨在为大家分享在文件操作中常用的输入输出函数的使用方式和技巧&#x…...
Harmony装饰器
1、装饰器 装饰器是用于装饰类、结构、方法以及变量,并赋予其特殊的含义。如: Component表示自定义组件Entry表示该自定义组件为入口组件State表示组件中的状态变量,状态变量变化会触发UI刷新。 2 、语法范式 Builder/BuilderParam&#…...

如何加快Chrome谷歌浏览器下载速度?
用Chrome打开chrome://flags/...

使用kubectl连接远程Kubernetes(k8s)集群
使用kubectl连接远程Kubernetes集群 环境准备下载kubectl下载地址 安装kubectl并处理配置文件Windows的安装配置安装kubectl拉取配置文件安装kubectl拉取配置文件kubectl命令自动补全 Linux的安装配置安装kubectl拉取配置文件kubectl命令自动补全 环境准备 你需要准备一个Kube…...

Kubernetes革命:云原生时代的应用编排和自动化
文章目录 什么是Kubernetes以及为何它备受欢迎?云原生应用和K8s的关系Kubernetes的核心概念:Pods、Services、ReplicaSets等部署、扩展和管理应用程序的自动化容器编排的演进:Docker到Kubernetes实际用例:企业如何受益于K8s的应用…...
mysql.mongoDb,neo4j数据库对比
#Mysql与MongoDb和Neo4j的一些对比 主要区别 MySQL: 1.MySQL是一种关系型数据库管理系统(RDBMS),广泛用于处理结构化数据。 2.它支持SQL语言,具备成熟的事务处理和数据一致性能力。 3.MySQL适用于大多数传统的基于表…...

unity使用UniStorm 5.1.0.unitypackage增加天气
添加天天气组件unistorm 然后添加一个player 导入包会报错,需要修改代码 using UnityEngine; using UnityEngine.PostProcessing;namespace UnityEditor.PostProcessing {[CustomPropertyDrawer(typeof(UnityEngine.PostProcessing.MinAttribute))]sealed class MinDrawer : …...

Flink实现kafka到kafka、kafka到doris的精准一次消费
1 流程图 2 Flink来源表建模 --来源-城市topic CREATE TABLE NJ_QL_JC_SSJC_SOURCE ( record string ) WITH (connector kafka,topic QL_JC_SSJC,properties.bootstrap.servers 172.*.*.*:9092,properties.group.id QL_JC_SSJC_NJ_QL_JC_SSJC_SOURCE,scan.startup.mode …...

Outlook屏蔽Jira AI提醒
前言:最近不知道为什么jira上的ai小助手抽风,一周发个几千封邮件…导致我现在都不想在邮箱里面跟找垃圾一样找消息了。实在忍无可忍,决定屏蔽AI小助手,方法很简单,follow me~~ 第一步:双击打开电脑版Outloo…...

毛玻璃 has 选择器卡片悬停效果
效果展示 页面结构 从上述的效果展示可以看到,页面是由多个卡片组成,并且鼠标悬停在卡片上时,会旋转用户图片并且韩式对应的用户信息框。 CSS3 知识点 :has 属性的运用 实现页面整体结构 <div class"container"><div…...
[hive]解决group by 字段超过系统规定64个
用开窗函数即可 ( row_number() over(partition by col1,...,col70 oder by xx) rn ) where rn1...
生成老年人的声音sox
sox laoren1.wav laoren2.wav pitch -300...

DC2DC电源设计注意事项--1,Feedback
电源采集图如下图 Feedback 采集电压点应该在靠近负载侧。这样可以减少大电流导线导致的电压差,真实反应输出电压值 FB_1P21采集电路靠近芯片侧, 2.1,采集分压电路上侧为Vout Vnoise, 那么一分压就噪声就小了。假如采集电路远离芯片侧&…...

计算机视觉处理的开源框架
计算机视觉是一门涉及图像和视频分析的领域,有许多开源的框架和库可用于构建计算机视觉应用程序。以下是一些常见的计算机视觉开源框架及其特点,希望对大家有所帮助。北京木奇移动技术有限公司,专业的软件外包开发公司,欢迎交流合…...

最新AI智能创作系统源码AI绘画系统/支持GPT联网提问/支持Prompt应用
AI绘图专业设计 不得将程序用作任何违法违纪内容,不要让亲人两行泪 界面部分图解构: 前台show: 前端部署: 安装pm2管理器 点击设置 选择v16.19.1版本-切换版本 再新建一个网站 点击设置 添加反向代理-代理名称随便…...
2019架构真题案例(四十八)
系统应用集成构件统一标准的基础平台,在各个应用系统的接口之间数据共享和功能,基本原则是保证应用程序的()。系统应用集成提供了四个不同层次的服务,最上层服务是()。 独立性相关性互操作性排…...

zabbix自定义监控内容和自动发现
6 目录 一、自定义监控内容: 1.明确需要执行的 linux 命令 2.创建 zabbix 的监控项配置文件,用于自定义 key: 3. 在 Web 页面创建自定义监控项模板: 3.1 创建模板: 3.2 创建监控项: 3.3 创建触发器&#…...

导引服务机器人 通用技术条件
声明 本文是学习GB-T 42831-2023 导引服务机器人 通用技术条件. 而整理的学习笔记,分享出来希望更多人受益,如果存在侵权请及时联系我们 6 检验规则 6.1 检验项目 检验分为型式检验和出厂检验。检验项目见表2。 表 2 检验项目 序号 检验项目 技术要求 检验方法 出厂检验 型…...

今日头条文章采集ChatGPT3.5/4.0驱动浏览器改写文章软件说明文档
大家好了,我是淘小白~ 今天给大家介绍的软件是一个款驱动浏览器改写文章的软件,下面给大家做一下介绍说明: 一、软件语言 Python编写的,使用的库是selenium库 二、具体逻辑 1、整理头条文章网址,需要自己整理&…...

Mac系统清理工具BuhoCleaner
BuhoCleaner是一款在Mac电脑上运行的清洁软件。它的界面简洁,易于使用,能够快速扫描Mac电脑上的垃圾文件、重复文件、大型文件等,帮助用户清理不需要的文件,释放磁盘空间。 该软件的主要功能包括: 垃圾文件清理&…...

Python实现prophet 理论及参数优化
文章目录 Prophet理论及模型参数介绍Python代码完整实现prophet 添加外部数据进行模型优化 之前初步学习prophet的时候,写过一篇简单实现,后期随着对该模型的深入研究,本次记录涉及到prophet 的公式以及参数调优,从公式可以更直观…...
将对透视变换后的图像使用Otsu进行阈值化,来分离黑色和白色像素。这句话中的Otsu是什么意思?
Otsu 是一种自动阈值化方法,用于将图像分割为前景和背景。它通过最小化图像的类内方差或等价地最大化类间方差来选择最佳阈值。这种方法特别适用于图像的二值化处理,能够自动确定一个阈值,将图像中的像素分为黑色和白色两类。 Otsu 方法的原…...

ardupilot 开发环境eclipse 中import 缺少C++
目录 文章目录 目录摘要1.修复过程摘要 本节主要解决ardupilot 开发环境eclipse 中import 缺少C++,无法导入ardupilot代码,会引起查看不方便的问题。如下图所示 1.修复过程 0.安装ubuntu 软件中自带的eclipse 1.打开eclipse—Help—install new software 2.在 Work with中…...
关于 WASM:1. WASM 基础原理
一、WASM 简介 1.1 WebAssembly 是什么? WebAssembly(WASM) 是一种能在现代浏览器中高效运行的二进制指令格式,它不是传统的编程语言,而是一种 低级字节码格式,可由高级语言(如 C、C、Rust&am…...

C++使用 new 来创建动态数组
问题: 不能使用变量定义数组大小 原因: 这是因为数组在内存中是连续存储的,编译器需要在编译阶段就确定数组的大小,以便正确地分配内存空间。如果允许使用变量来定义数组的大小,那么编译器就无法在编译时确定数组的大…...

Yolov8 目标检测蒸馏学习记录
yolov8系列模型蒸馏基本流程,代码下载:这里本人提交了一个demo:djdll/Yolov8_Distillation: Yolov8轻量化_蒸馏代码实现 在轻量化模型设计中,**知识蒸馏(Knowledge Distillation)**被广泛应用,作为提升模型…...

推荐 github 项目:GeminiImageApp(图片生成方向,可以做一定的素材)
推荐 github 项目:GeminiImageApp(图片生成方向,可以做一定的素材) 这个项目能干嘛? 使用 gemini 2.0 的 api 和 google 其他的 api 来做衍生处理 简化和优化了文生图和图生图的行为(我的最主要) 并且有一些目标检测和切割(我用不到) 视频和 imagefx 因为没 a…...

Python Ovito统计金刚石结构数量
大家好,我是小马老师。 本文介绍python ovito方法统计金刚石结构的方法。 Ovito Identify diamond structure命令可以识别和统计金刚石结构,但是无法直接输出结构的变化情况。 本文使用python调用ovito包的方法,可以持续统计各步的金刚石结构,具体代码如下: from ovito…...

【MATLAB代码】基于最大相关熵准则(MCC)的三维鲁棒卡尔曼滤波算法(MCC-KF),附源代码|订阅专栏后可直接查看
文章所述的代码实现了基于最大相关熵准则(MCC)的三维鲁棒卡尔曼滤波算法(MCC-KF),针对传感器观测数据中存在的脉冲型异常噪声问题,通过非线性加权机制提升滤波器的抗干扰能力。代码通过对比传统KF与MCC-KF在含异常值场景下的表现,验证了后者在状态估计鲁棒性方面的显著优…...
Git 命令全流程总结
以下是从初始化到版本控制、查看记录、撤回操作的 Git 命令全流程总结,按操作场景分类整理: 一、初始化与基础操作 操作命令初始化仓库git init添加所有文件到暂存区git add .提交到本地仓库git commit -m "提交描述"首次提交需配置身份git c…...