Linux中的三类读写函数
文件IO和标准IO的区别
- 遵循标准:
- 文件IO遵循POSIX标准,主要在类UNIX环境下使用。
- 标准IO遵循ANSI标准,具有更好的可移植性,可以在不同的操作系统上重新编译后运行。
- 可移植性:
- 文件IO的可移植性相对较差,因为它与系统底层紧密相关。
- 标准IO的可移植性较好,因为它是C语言标准库的一部分,可以在不同的操作系统上移植使用。
- 操作方式:
- 文件IO通过系统调用来直接读写文件,每次操作都会触发系统调用。
- 标准IO在内部实现了缓冲机制,通过文件流指针来操作文件,减少了系统调用的次数,提高了性能。
- 缓冲机制:
- 文件IO通常不带缓冲,每次读写操作都会直接与系统底层交互。
- 标准IO带缓冲,先将数据写入缓冲区,再选择合适时机将缓冲区中的数据写入文件或从文件中读取数据到缓冲区。
- 访问的文件类型:
- 文件IO可以访问不同类型的文件,包括普通文件、设备文件、管道文件和套接字文件等。
- 标准IO主要用于访问普通文件,虽然也可以重定向到其他类型的设备,但其本质还是通过文件流指针来操作文件。
- 使用的接口:
- 文件IO使用如open、read、write、close等系统调用接口。
- 标准IO使用如fopen、fread、fwrite、fclose等C标准库函数接口。
Linux标准文件描述符
我们使用printf和write都可以输出正常的字符串
当我们给程序加上一条死循环的程序,就会发现用printf()不能继续执行,而用write可以继续执行。
这个原因就是因为缓存问题,见下文
缓存的概念
1.我们的程序中的缓存,就是你想从内核读写的缓存(数组)----用户空间的缓存
2.每打开一个文件,内核在内核空间中也会开辟一块缓存,这个叫内核空间的缓存
文件IO中的写即是将用户空间中的缓存写到内核空间的缓存中。
文件IO中的读即是将内核空间的缓存写到用户空间中的缓存中。
3.标准IO的库函数中也有一个缓存,这个缓存称为----库缓存
C库缓存的特点:
1.遇到\n 时,会将库缓存的内容写到内核缓存中,即调用了系统调用函数。
2.库缓存写满时,会调用系统调用函数,将库缓存内容写到内核缓存中。当写满时,即1024字节
关于上面的问题,使用write函数就是文件IO,它可以直接将用户空间(我们给文件的数据)写道内存空间中,当我们使用C库printf时,他不会直接调用而是等待写满才会系统调用函数将库缓存写道内核缓存中,为了使能够输出我们给文件的数据(hello world),我们可以在输入后面加一个\n使其成功打印(还是和正常输出略有不同)
三类读写缓存
fputs函数
属于C语言标准库函数,用于将一个字符串写入到指的头文件中,写入成功后光标会移到写入的最后一个字符
函数原型
int fputs(const char *str, FILE *stream);
str
:指向要写入文件的字符串的指针。stream
:指向FILE
对象的指针,该FILE
对象标识了要写入数据的文件流。
fputs
函数将str
指向的字符串写入到stream
指定的文件流中,但不包括空字符('\0'
)。如果写入成功,fputs
返回一个非负整数;如果发生错误,则返回EOF
。
fgets函数
用于从指定的文件流中读取一行,使用 fgets
可以很方便地从文件或者标准输入(如键盘)读取字符串,直到遇到换行符或文件结束符,或者达到指定的字符数。
函数原型:
char *fgets(char *str, int n, FILE *stream);
str
:指向一个字符数组的指针,用来存储读取到的字符串。n
:指定最多读取的字符数,包括最后的空字符(\0
),因此实际上最多能读取n-1
个字符。stream
:指定从哪个文件流中读取数据。
返回值
- 成功时,返回
str
。 - 失败或到达文件末尾时,返回
NULL
。
注意文件的权限,应该是w+,可读可写!!!!
fflush函数
用于刷新缓冲区,
fflush
函数用于将给定的输出流或更新流stream
的缓冲区中的数据强制写入到对应的文件或设备中。如果stream
指向的是一个输出流或者是一个最近一次操作不是输入的更新流,则fflush
会将缓冲区中未写入的数据写入到流指向的文件或设备中。- 如果
stream
是空指针(NULL
),则fflush
会对所有打开的文件流执行刷新操作。
函数原型
int fflush(FILE *stream);
返回值:
- 成功时,
fflush
返回0
。 - 如果发生错误,则返回
EOF
,并且设置相应的错误标识符。
第一种:刷新标准输出缓冲区
fflush(stdout)
确保printf
函数输出的内容立即被写入到标准输出设备(通常是屏幕)上。
第二种:刷新文件流缓冲区
在这个例子中,fflush(file)
确保通过fprintf
函数写入到file
指向的文件中的数据被立即写入到磁盘上。注意,虽然在这个例子中fflush
的调用是可选的(因为关闭文件时会自动刷新缓冲区)
stderr无缓冲函数
stderr
是C语言标准I/O库中的一个特殊文件流,代表标准错误输出。与标准输出stdout
不同,stderr
通常是无缓冲的,这意味着写入stderr
的数据会立即输出,而不会被缓存在内存中。
由于stderr
是无缓冲的,因此它非常适合用于输出错误信息或日志,因为这些信息通常需要立即显示在屏幕上,以便用户或开发人员能够及时发现并处理问题。
stderr与stdout的区别
stdout
是标准输出流,它通常是行缓冲或全缓冲的。这意味着写入stdout
的数据可能会被缓存在内存中,直到遇到换行符或缓冲区满时才真正输出。而stderr
则不同,它无缓冲的特性确保了数据的即时输出。
在这个例子中,我们尝试打开一个不存在的文件。由于文件不存在,fopen
函数将返回NULL
,并且我们通过fprintf
函数将一条错误信息写入stderr
。由于stderr
是无缓冲的,这条错误信息将立即显示在屏幕上。
stderr
作为标准错误输出流,其无缓冲的特性使得它非常适合用于输出错误信息或日志。在使用时,我们只需要将错误信息或日志写入stderr
,它们就会立即显示在屏幕上,无需担心缓冲导致的问题。
rewind
也属于C语言标准库函数,该函数的主要作用是将文件内部的位置指针(也称为文件位置指示器)重新指向一个文件流(数据流/文件)的开头。
所以此函数的作用和fseek中的一个作用相同(SEEK_SET)
gets函数
函数原型
char *gets(char *s);
gets 与fgets的区别:
gets()时不能指定缓存的长度,这样就可能造成缓存越界(如若该行长于缓存长度),写到缓存之后的存储空 间中,从而产生不可预料的后果;
gets()只能从标准输入中读;
gets()与fgets()的另一个区别是:gets()并不将新行符存入缓存中, fgets 将新行符存入缓存中;
用gets容易越界,写入缓存时不会把换行符\n算进字符长度
fgets会把换行符算进字符长度,不会越界
puts函数
函数原型:
int puts(const char *str);
puts 与fputs的区别:
puts()只能向标准输出中写;
puts()与fputs()的另一个区别是: puts 输出时会添加一个新行符,fputs不会添加;
比gets多一个换行操作(\n)。
fgetc函数
从文件中读取一个字符
int fgetc(FILE *fp)
参数:字符流
返回值:正确为读取的字符文件结尾或出错返回-1。
fputc函数
功能:写一个字符到文件中
参数:第一个参数为要写的字符,第二个参数为文件流
返回值:成功则返回输入的字符,出错返回EOF。-1
fputc有缓存,但不是行缓存函数
当读到a时已经是最后一位了,所以再次读就会按照函数规则返回-1
行缓存函数
fprintf函数
通过文件流指针来控制输出的目标,通常用于将信息写入到指定的文件或标准输出流(如stdout或stderr)中。
fprintf的原型函数为:
int fprintf(FILE *stream, const char *format, ...);
FILE *stream
:指向输出流的文件指针,决定了数据将被写入哪个文件或输出流。
const char *format
:格式化字符串,用于指定后续参数如何被格式化和输出。
...:可变参数列表,包含了一系列将要被格式化和输出的数据。
fprintf函数的返回值是写入的字符数(不包括终止的空字符),如果发生错误则返回负值。
第一个fprintf是写入一行文本到example.txt这个文件中
第二个fprintf是写入一行文本到标准输出中,(通常是屏幕)。
sprintf函数
sprintf是C语言中的一个字符串格式化函数,其函数声明为:
int sprintf(char *str, const char *format, ...);
char *str
:指向一个字符数组的指针,该数组用于存储格式化后的字符串。const char *format
:格式化字符串,指定了如何将后续参数格式化为字符串。...
:可变参数列表,包含了一系列将要被格式化和插入到str
所指向字符串中的数据。
sprintf函数将格式化的数据写入到str
指向的字符串中,并返回写入的字符数(不包括终止的空字符)。需要注意的是,使用sprintf时需要确保目标字符串str
有足够的空间来存储格式化后的结果,否则可能会导致缓冲区溢出。
一般情况下,sprintf函数和printf函数一起使用,sprintf是用来把数据写入到字符串当中,并不起到输出作用
cat指令的实现
用fgetc和fputc
通过一个个字符的读写从而使cat查看指令实现
注:feof函数用来判断是否已经到文件结束(如果文件结束则返回非0,没有则返回0)
if(argv!=2)表示若不是只有一个命令行,则操作失败
三个判断函数
int feof(FILE *stream);
功能:判断是否已经到文件结束
参数:文件流
返回值:到文件结束,返回为非0,没有则返回0
int ferror(FILE *stream);
功能:判断是否读写错误
参数:文件流 返
回值:是读写错误,返回为非0,不是则返回0
void clearerr(FILE *stream);
功能:清除流错误
参数:文件流
清除错误标志(通常是通过调用clearerr
函数)对程序的影响主要体现在以下几个方面:
-
恢复文件流状态:当文件流(如通过
FILE *
类型表示的文件指针)遇到错误(如读写错误)或到达文件末尾(EOF)时,相应的错误标志或EOF标志会被设置。这些标志会影响后续的输入输出操作。通过清除这些标志,clearerr
函数将文件流恢复到一种“干净”的状态,使得后续操作可以不受之前错误或EOF状态的影响。 -
允许继续执行:在某些情况下,文件流错误可能是暂时的或者可以通过某些方式解决(例如,通过重新定位文件指针、关闭并重新打开文件或修改文件访问模式)。清除错误标志后,程序可以继续尝试执行之前失败的操作,或者执行其他依赖于文件流状态的操作。
-
错误处理:在清除错误标志之前,程序可能会根据错误状态执行特定的错误处理代码(如打印错误消息、释放资源、尝试恢复等)。清除错误标志后,这些错误处理代码可能不再适用,因为错误状态已经被重置。因此,程序需要适当地调整其错误处理逻辑,以考虑错误标志被清除后的情况。
-
文件结束(EOF)的重新评估:如果文件流遇到了EOF,并且随后调用了
clearerr
来清除EOF标志,那么程序可能会错误地认为文件尚未结束,并尝试继续读取数据。这可能会导致未定义的行为,如读取到无效的数据或进入无限循环。因此,在清除EOF标志之前,程序应该仔细考虑其后果,并确保这是期望的行为。 -
对后续操作的潜在影响:清除错误标志可能会影响到依赖于这些标志来检测文件状态变化的后续操作。例如,如果程序依赖于
feof
函数来检测文件是否结束,那么在清除EOF标志后,feof
将不再返回真值,直到文件流再次真正到达文件末尾。
相关文章:

Linux中的三类读写函数
文件IO和标准IO的区别 遵循标准: 文件IO遵循POSIX标准,主要在类UNIX环境下使用。标准IO遵循ANSI标准,具有更好的可移植性,可以在不同的操作系统上重新编译后运行。可移植性: 文件IO的可移植性相对较差,因为…...
MATLAB基础应用精讲-【数模应用】二元Probit回归分析
目录 前言 知识储备 二元Logistic模型和Probit模型 Logistic模型的形式 Probit模型 优势比(OR) 准二项分布族 算法原理 数学模型 二元因变量和线性概率模型 probit和logit回归 logit和probit模型的估计和推断 稳健性检验 二元logit回归分析全流程 一、案例数…...

找工作准备刷题Day10 回溯算法 (卡尔41期训练营 7.24)
回溯算法今天这几个题目做过,晚上有面试,今天水一水。 第一题:Leetcode77. 组合 题目描述 解题思路 从题目示例来看,k个数是不能重合的,但是题目没有明确说明这一点。 使用回溯算法解决此问题,利用树形…...

如何有效的进行小程序的优化
如今小程序已经成为了许多开发者开展业务,提供服务的重要平台 。所以如何有效的优化小程序成为了开发者关注的首要问题,以下是一份详细的小程序优化方案: 一、目标设定 明确小程序优化的主要目标,例如提高用户留存率、增加用户活…...

FPGA-ROM IP核的使用(2)
前言 接着昨天的进行一个小的实验验证ROM IP核。 实验效果 读取上一期生成的IP核中的数据,并将其显示在数码管上。 具体流程 ROM IP核存放数据0~255,之后每隔0.2s,从0的地址开始读数据,并显示在数码管上;接着先后…...

Manticore Search(es轻量级替代)
概念: Manticore Search 是一个使用 C 开发的高性能搜索引擎,创建于 2017 年,其前身是 Sphinx Search 。Manticore Search 充分利用了 Sphinx,显着改进了它的功能,修复了数百个错误,几乎完全重写了代码并保…...
测试开发面试题---计算机网络
计算机网络模型 OSI模型:七层模型 物理层:定义电气特征,机械特征等功能规范,传递实际比特流数据链路层:物理地址寻址(MAC),帧的传输,错误检测和纠正网络层:…...

Wonder3D 论文学习
论文链接:https://arxiv.org/abs/2310.15008 代码链接:https://github.com/xxlong0/Wonder3D 解决了什么问题? 随着扩散模型的提出,3D 生成领域取得了长足进步。从单张图片重建出 3D 几何是计算机图形学和 3D 视觉的基础任务&am…...
【MySQL进阶之路 | 高级篇】显式事务和隐式事务
使用事务有两种方式:显式事务和隐式事务。 1. 显式事务 步骤1: START TRANSACTION或者BEGIN,作用是显式开启一个事务。 START TRANSACTION语句相较于BEGIN特别之处在于,后面能跟几个修饰符。比如: READ ONLY&…...

Ruby、Python、Java 开发者必备:Codigger之软件项目体检
在编程的广阔天地里,Ruby、Python 和 Java 开发者们各自凭借着独特的语言特性,构建着精彩纷呈的应用世界。然而,无论使用哪种语言,确保项目的高质量始终是至关重要的目标。而 Codigger 项目体检则成为了实现这一目标的得力助手&am…...

day05 Router、vuex、axios
配置 router和vuex需要在创建vue项目的时候,开始的时候选择Manually select features,于是就可以在下一个创建配置讯问中选择router和vuex。 axios则需要执行命令行: npm install axios -S 之后再在需要发送请求的view导入即可。 router…...

yolov5-7在opencv里跑自己的onnx模型
先把模型放在如下目录 运行如下代码 import cv2 import numpy as npclass Onnx_clf:def __init__(self, onnx:strdnn_model1/plane02.onnx, img_size640, classlist:list[plane]) -> None: func: 读取onnx模型,并进行目标识别para onnx:模型路径img_size:输出图片大小,和模…...
JVM 11 的优化指南:如何进行JVM调优,JVM调优参数有哪些
这篇文章将详细介绍如何进行JVM 11调优,包括JVM 11调优参数及其应用。此外,我将提供12个实用的代码示例,每个示例都会结合JVM启动参数和Java代码。 本文已收录于,我的技术网站 java-broke.site,有大厂完整面经&#x…...

nginx的配置和使用
一、nginx支持win和linux版本的下载,选择合适的版本进行安装 二、配置文件注解 重点的几个参数进行注释: 1、listen 要监听的服务的端口,符合这个端口的才会被监听 server_name要监听的服务地址,可能是ip,也可能是域名…...

mysql面试(六)
前言 本章节详细讲解了一下mysql执行计划相关的属性释义,以及不同sql所出现的不同效果 执行计划 一条查询语句经过mysql查询优化器的各种基于成本和各种规则优化之后,会生成一个所谓的 执行计划,这个执行计划展示了这条查询语句具体查询方…...

6.乳腺癌良性恶性预测(二分类、逻辑回归、PCA降维、SVD奇异值分解)
乳腺癌良性恶性预测 1. 特征工程1.1 特征筛选1.2 特征降维 PCA1.3 SVD奇异值分解 2. 代码2.1 逻辑回归、二分类问题2.2 特征降维 PCA2.3 SVD奇异值分解 1. 特征工程 专业上:30个人特征来自于临床一线专家,每个特征和都有医学内涵;数据上&…...
Vue3响应式高阶用法之markRaw()
Vue3响应式高阶用法之markRaw() 文章目录 Vue3响应式高阶用法之markRaw()一、简介二、使用场景2.1 避免性能开销2.2 防止意外修改 三、基本使用3.1 标记对象 四、功能详解4.1 markRaw与reactive的区别4.2 markRaw与ref的区别 五、最佳实践及案例5.1 使用大型第三方库对象5.2 静…...

免费SSL证书的安全性与获取指南
SSL证书是一种数字凭证,用于加密用户与网站之间的信息交换,以确保传输的数据不被第三方窃取。它像是一个数字版的密封印章,为数据的传输过程提供了一层保护膜。 免费的SSL证书通常由CA机构提供,它们同样可以提供基础数据的加密服…...

【CN】Argo 持续集成和交付(一)
1.简介 Argo 英 [ˈɑ:ɡəu] 美 [ˈɑrˌɡo] Kubernetes 原生工具,用于运行工作流程、管理集群以及正确执行 GitOps。 Argo 于 2020 年 3 月 26 日被 CNCF 接受为孵化成熟度级别,然后于 2022 年 12 月 6 日转移到毕业成熟度级别。 argoproj.github.i…...
Unity3D 自定义Debug双击溯源问题详解
前言 在Unity3D的开发过程中,经常需要处理各种交互和事件,其中双击事件是常见的需求之一。然而,由于Unity自带的双击检测机制并不完善,开发者往往需要自定义实现以满足特定需求。本文将详细介绍如何在Unity3D中自定义Debug双击溯…...

云原生玩法三问:构建自定义开发环境
云原生玩法三问:构建自定义开发环境 引言 临时运维一个古董项目,无文档,无环境,无交接人,俗称三无。 运行设备的环境老,本地环境版本高,ssh不过去。正好最近对 腾讯出品的云原生 cnb 感兴趣&…...
Linux C语言网络编程详细入门教程:如何一步步实现TCP服务端与客户端通信
文章目录 Linux C语言网络编程详细入门教程:如何一步步实现TCP服务端与客户端通信前言一、网络通信基础概念二、服务端与客户端的完整流程图解三、每一步的详细讲解和代码示例1. 创建Socket(服务端和客户端都要)2. 绑定本地地址和端口&#x…...

面向无人机海岸带生态系统监测的语义分割基准数据集
描述:海岸带生态系统的监测是维护生态平衡和可持续发展的重要任务。语义分割技术在遥感影像中的应用为海岸带生态系统的精准监测提供了有效手段。然而,目前该领域仍面临一个挑战,即缺乏公开的专门面向海岸带生态系统的语义分割基准数据集。受…...

【 java 虚拟机知识 第一篇 】
目录 1.内存模型 1.1.JVM内存模型的介绍 1.2.堆和栈的区别 1.3.栈的存储细节 1.4.堆的部分 1.5.程序计数器的作用 1.6.方法区的内容 1.7.字符串池 1.8.引用类型 1.9.内存泄漏与内存溢出 1.10.会出现内存溢出的结构 1.内存模型 1.1.JVM内存模型的介绍 内存模型主要分…...
xmind转换为markdown
文章目录 解锁思维导图新姿势:将XMind转为结构化Markdown 一、认识Xmind结构二、核心转换流程详解1.解压XMind文件(ZIP处理)2.解析JSON数据结构3:递归转换树形结构4:Markdown层级生成逻辑 三、完整代码 解锁思维导图新…...

【Linux】Linux安装并配置RabbitMQ
目录 1. 安装 Erlang 2. 安装 RabbitMQ 2.1.添加 RabbitMQ 仓库 2.2.安装 RabbitMQ 3.配置 3.1.启动和管理服务 4. 访问管理界面 5.安装问题 6.修改密码 7.修改端口 7.1.找到文件 7.2.修改文件 1. 安装 Erlang 由于 RabbitMQ 是用 Erlang 编写的,需要先安…...
数据库正常,但后端收不到数据原因及解决
从代码和日志来看,后端SQL查询确实返回了数据,但最终user对象却为null。这表明查询结果没有正确映射到User对象上。 在前后端分离,并且ai辅助开发的时候,很容易出现前后端变量名不一致情况,还不报错,只是单…...
Java并发编程实战 Day 11:并发设计模式
【Java并发编程实战 Day 11】并发设计模式 开篇 这是"Java并发编程实战"系列的第11天,今天我们聚焦于并发设计模式。并发设计模式是解决多线程环境下常见问题的经典解决方案,它们不仅提供了优雅的设计思路,还能显著提升系统的性能…...
CppCon 2015 学习:Reactive Stream Processing in Industrial IoT using DDS and Rx
“Reactive Stream Processing in Industrial IoT using DDS and Rx” 是指在工业物联网(IIoT)场景中,结合 DDS(Data Distribution Service) 和 Rx(Reactive Extensions) 技术,实现 …...

高抗扰度汽车光耦合器的特性
晶台光电推出的125℃光耦合器系列产品(包括KL357NU、KL3H7U和KL817U),专为高温环境下的汽车应用设计,具备以下核心优势和技术特点: 一、技术特性分析 高温稳定性 采用先进的LED技术和优化的IC设计,确保在…...