Linux中的三类读写函数

文件IO和标准IO的区别

  1. 遵循标准
    • 文件IO遵循POSIX标准,主要在类UNIX环境下使用。
    • 标准IO遵循ANSI标准,具有更好的可移植性,可以在不同的操作系统上重新编译后运行。
  2. 可移植性
    • 文件IO的可移植性相对较差,因为它与系统底层紧密相关。
    • 标准IO的可移植性较好,因为它是C语言标准库的一部分,可以在不同的操作系统上移植使用。
  3. 操作方式
    • 文件IO通过系统调用来直接读写文件,每次操作都会触发系统调用。
    • 标准IO在内部实现了缓冲机制,通过文件流指针来操作文件,减少了系统调用的次数,提高了性能。
  4. 缓冲机制
    • 文件IO通常不带缓冲,每次读写操作都会直接与系统底层交互。
    • 标准IO带缓冲,先将数据写入缓冲区,再选择合适时机将缓冲区中的数据写入文件或从文件中读取数据到缓冲区。
  5. 访问的文件类型
    • 文件IO可以访问不同类型的文件,包括普通文件、设备文件、管道文件和套接字文件等。
    • 标准IO主要用于访问普通文件,虽然也可以重定向到其他类型的设备,但其本质还是通过文件流指针来操作文件。
  6. 使用的接口
    • 文件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函数)对程序的影响主要体现在以下几个方面:

  1. 恢复文件流状态:当文件流(如通过FILE *类型表示的文件指针)遇到错误(如读写错误)或到达文件末尾(EOF)时,相应的错误标志或EOF标志会被设置。这些标志会影响后续的输入输出操作。通过清除这些标志,clearerr函数将文件流恢复到一种“干净”的状态,使得后续操作可以不受之前错误或EOF状态的影响。

  2. 允许继续执行:在某些情况下,文件流错误可能是暂时的或者可以通过某些方式解决(例如,通过重新定位文件指针、关闭并重新打开文件或修改文件访问模式)。清除错误标志后,程序可以继续尝试执行之前失败的操作,或者执行其他依赖于文件流状态的操作。

  3. 错误处理:在清除错误标志之前,程序可能会根据错误状态执行特定的错误处理代码(如打印错误消息、释放资源、尝试恢复等)。清除错误标志后,这些错误处理代码可能不再适用,因为错误状态已经被重置。因此,程序需要适当地调整其错误处理逻辑,以考虑错误标志被清除后的情况。

  4. 文件结束(EOF)的重新评估:如果文件流遇到了EOF,并且随后调用了clearerr来清除EOF标志,那么程序可能会错误地认为文件尚未结束,并尝试继续读取数据。这可能会导致未定义的行为,如读取到无效的数据或进入无限循环。因此,在清除EOF标志之前,程序应该仔细考虑其后果,并确保这是期望的行为。

  5. 对后续操作的潜在影响:清除错误标志可能会影响到依赖于这些标志来检测文件状态变化的后续操作。例如,如果程序依赖于feof函数来检测文件是否结束,那么在清除EOF标志后,feof将不再返回真值,直到文件流再次真正到达文件末尾。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/3267271.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

MAC、ARP、NAT

文章目录 MACMAC帧格式MAC地址 ARP协议ARP的数据包格式 NAT和代理IP地址的数量限制NAT代理服务器 MAC 数据在局域网中如何发送就是数据链路层解决的。 MAC帧格式 源地址和目的地址是指网卡的硬件地址(也叫MAC地址), 长度是48位,是在网卡出厂时固化的。 帧协议类型字段有三种值…

AI在招聘领域的应用:提高效率、降低成本与增强候选人体验

一、引言 在数字化浪潮席卷全球的今天,人工智能(AI)技术已经渗透到社会的各个领域,其中也包括人力资源管理中的招聘环节。AI技术的引入不仅为企业带来了前所未有的便利,更在提升招聘效率、降低成本以及增强候选人体验等…

Spring Boot入门指南:留言板

一.留言板 1.输⼊留⾔信息,点击提交.后端把数据存储起来. 2.⻚⾯展⽰输⼊的表⽩墙的信息 规范: 1.写一个类MessageInfo对象,添加构造方法 虽然有快捷键,但是还是不够偷懒 项目添加Lombok。 Lombok是⼀个Java⼯具库,通过添加注…

【年报文本分析】Python+Selium获取互动易平台投资者提问与上市公司回应文本数据

目录 序言excel文件准备全部代码 序言 互动易平台链接:https://irm.cninfo.com.cn/views/interactiveAnswer 需要提前下载好三个库,都可以用pip install轻松下载,稍微麻烦点儿的是需要去下载个对应版本的chromedriver.exe驱动,放…

Android 生成Excel并导出全流程

前言 最近接到需求,要在安卓上离线完成根据数据生成Excel文件,但搜到了都不是能立马使用 例如 // implementation org.apache.poi:poi:3.17 // implementation com.alibaba:easyexcel:4.0.1 这两最大的问题是专用于java的,如果And…

git sendemail使用

教程参考: git-send-email - 以电子邮件形式发送补丁集 1、安装git-email 2、配置 SMTP 服务器 git config --global sendemail.smtpserver smtp.163.com git config --global sendemail.smtpserverport 465 git config --global sendemail.smtpuser xxxxxx163.c…

恒创科技:如何排查和解决服务器高负载问题?

服务器负载过高是业务正常运行的主要威胁之一。高平均负载意味着系统或服务器超载,许多进程正在等待 CPU 时间。因此将有许多进程等待完成,这些进程将进入队列,导致服务器负载增加。 高负载的主要原因 1.服务器超载 2.垃圾邮件 3.硬盘性能 4.…

Navicat Premium Lite数据库管理软件

首先我们大家可以通过下面的地址下载我们的Navicat Premium Lite: https://www.navicat.com.cn/products/navicat-premium-lite 1、Navicat精简版 2、下载 3、运行界面 。。。

前端面试项目细节重难点分享(十三)

面试题提问:分享你最近做的这个项目,并讲讲该项目的重难点? 答:最近这个项目是一个二次迭代开发项目,迭代周期一年,在做这些任务需求时,确实有很多值得分享的印象深刻的点,我讲讲下面…

【Linux】基本指令1

文章目录 1. find2. which3. alias4.whereis5.grep6. sort 、uniq7. linux怎么编辑文件中的内容 1. find 1.1 find: 查找文件所在的位置。(当我们进行find搜索的时候,可能需要访问磁盘进而导致效率低下。) 1.2 find / file.txt 在Linux系统是…

Qt自定义MessageToast

效果&#xff1a; 文字长度自适应&#xff0c;自动居中到parent&#xff0c;会透明渐变消失。 CustomToast::MessageToast(QS("最多添加50张图片"),this);1. CustomToast.h #pragma once#include <QFrame>class CustomToast : public QFrame {Q_OBJECT pub…

MinIO存储桶通知 - Kafka小测

概述 公司的某个项目需要用上这玩意&#xff0c;所以在本地搭建测试环境&#xff0c;经过一番折腾&#xff0c;测试通过&#xff0c;博文记录&#xff0c;用以备忘 MinIO安装 该节不做说明&#xff0c;网络有很多现成的帖子&#xff0c;自行搜索去 配置步骤 控制台添加事件…

ROS2入门到精通—— 2-11 ROS2实战:实现基于voronoi_planner的全局规划(一)!!!保姆级教程

实现基于voronoi_planner的全局规划将分为两篇博文进行讲解 本文参考该大佬代码: https://github.com/nkuwenjian/voronoi_planner.githttps://github.com/nkuwenjian/voronoi_layer.git将上面的ROS1代码移植到ROS2,移植不易,中间遇到很多坑 0 前言 针对一些狭窄区域,可能…

海山数据库(He3DB)性能优化方案解析

前端优化是一个永恒的话题&#xff0c;每个前端开发者都希望自己的页面能够快速加载&#xff0c;给用户良好的体验。但往往事与愿违。因此&#xff0c;本文从编码优化、构建优化、部署优化三方面入手进行web页面性能优化。 1. 编码优化 1.1. Css优化 1.1.1. 合理使用css选择…

谷粒商城实战笔记-60-商品服务-API-品牌管理-效果优化与快速显示开关

文章目录 一&#xff0c;显示状态列改为switch开关二&#xff0c;监听状态改变 首先&#xff0c;把ESLint语法检查关掉&#xff0c;因为这个语法检查过于严格&#xff0c;在控制台输出很多错误信息&#xff0c;干扰开发。 在build目录下下webpack.base.conf.js中&#xff0c;把…

python基础巩固

基本数据类型 可以用isinstance来判断 a111 isinstance(a,int) True数值运算&#xff1a; >>> 2 / 4 # 除法&#xff0c;得到一个浮点数 0.5 >>> 2 // 4 # 除法&#xff0c;得到一个整数 0 >>> 17 % 3 # 取余 2Python 字符串不能被改变。向一个…

【LLM】-08-搭建问答系统-语言模型,提问范式与 Token

目录 1、语言模型 1.1、训练过程&#xff1a; 1..2、大型语言模型分类&#xff1a; 1.3、指令微调模型训练过程&#xff1a; 2、Tokens 3、Helper function辅助函数 (提问范式) 4、计算token数量 1、语言模型 大语言模型&#xff08;LLM&#xff09;是通过预测下一个词…

由bext安装“异常”引出的话题:windows上转义字符的工作原理

由bext安装“异常”引出的话题&#xff1a;Windows上转义字符的工作原理&#xff0c;与ai“闲扯”不经意学习知识点。 (笔记模板由python脚本于2024年07月25日 19:21:13创建&#xff0c;本篇笔记适合喜欢用ai学习的coder翻阅) 【学习的细节是欢悦的历程】 Python 官网&#xff…

【Ubuntu】安装 Snipaste 截图软件

Snipaste 下载安装并使用 Snipastefor more information报错解决方案每次启动软件需要输入的命令如下添加开机自启动 下载 下载地址 安装并使用 Snipaste 进入终端输入命令 # 1、进入到 Snipaste-2.8.9-Beta-x86_64.AppImage 所在目录&#xff08;根据自己的下载目录而定&…

pythonGame-实现简单的贪食蛇游戏

通过python简单复现贪食蛇游戏。 使用到的库函数&#xff1a; import pygame import time import random 游戏源码&#xff1a; import pygame import time import randompygame.init()white (255, 255, 255) yellow (255, 255, 102) black (0, 0, 0) red (213, 50, 80…