Linux中的三类读写函数

news2024/11/24 11:34:08

文件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://www.coloradmin.cn/o/1951282.html

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

相关文章

从丢失到找回:2024年U盘数据恢复软件全攻略

优盘作为我们日常短时间存储分享数据来说非常方便,毕竟小巧便携。但是也正因为他小巧数据很容易丢失,如果有备份还好,没有备份就麻烦了。但是只要掌握U盘数据恢复方法就可以缩小我们的损失。 1.福foxit昕数据恢复工具 一键直达>>http…

【ESP32 idf 硬件I2C驱动MPU6050获取六轴数值】

目录 I2C介绍配置安装驱动通信创建&删除命令链接容器起始时序写数据读数据结束时序开始命令 mpu6050 硬件i2c驱动代码&调试代码调试 I2C 介绍 介绍部分可以看我写的【ESP32 idf 软件模拟I2C驱动MPU6050实现六轴加速度的获取】,这个是使用软件模拟的I2C时序…

数据结构-C语言-排序(4)

代码位置: test-c-2024: 对C语言习题代码的练习 (gitee.com) 一、前言: 1.1-排序定义: 排序就是将一组杂乱无章的数据按照一定的规律(升序或降序)组织起来。(注:我们这里的排序采用的都为升序) 1.2-排…

找工作准备刷题Day10 回溯算法 (卡尔41期训练营 7.24)

回溯算法今天这几个题目做过,晚上有面试,今天水一水。 第一题:Leetcode77. 组合 题目描述 解题思路 从题目示例来看,k个数是不能重合的,但是题目没有明确说明这一点。 使用回溯算法解决此问题,利用树形…

设计模式-结构型-09-外观模式

文章目录 1、影院管理项目2、外观模式基本介绍4、MyBatis 框架源码分析5、外观模式总结 1、影院管理项目 组建一个家庭影院: DVD 播放器、投影仪、自动屏幕、环绕立体声、爆米花机,要求完成使用家庭影院的功能,其过程为: 直接用…

推荐一个酷炫高逼格的服务器探针的监控工具,免费开源(附源码)

背景 作为一名攻城狮,面对各种服务器内存飙高、CPU猛增、磁盘打满等等服务器问题,可谓是伤透了我们的心。 不仅要开发,还要处理这些问题,大把的时间浪费了,这时候一个好的全面的监控工具尤为重要了。 所以&#xff…

Spring AI (三) 提示词对象Prompt

3.提示词对象Prompt 3.1.Prompt Prompt类的作用是创建结构化提示词, 实现了ModelRequest<List<Message>>接口 Prompt(String contents)&#xff1a;创建一个包含指定内容的Prompt对象。 Prompt(String contents, ChatOptions modelOptions)&#xff1a;创建一个…

Github 2024-07-26 Java开源项目日报 Top10

根据Github Trendings的统计,今日(2024-07-26统计)共有10个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量Java项目9HTML项目1TypeScript项目1非开发语言项目1JavaGuide - Java 程序员学习和面试指南 创建周期:2118 天开发语言:Java协议类型:Apache…

【C++】初识C++基础篇·一(命名空间,函数重载,缺省参数,引用);

文章目录 前言1.输入与输出输出输入cin和scanf的对比 2.命名空间2.1namespace存在的意义2.2namespace的使用3.缺省参数4.函数重载重载函数的调用规则 5.引用 前言 我们先通过一段简单的代码来拉开C的序幕&#xff1b; //text.cpp #include<iostream> #include<stdio…

C++知识点总结:3.C++引用(自用)

C引用 1. 引用定义2. 引用的本质3. 引用和指针的不同之处补充指针常量和常量指针 4. 引用不能指代临时变量5. const引用&#xff08;常引用&#xff09;可以绑定临时数据6. const引用与转换类型 引用&#xff1a; [1]C语言中文网 [2]偶尔e网事,【C基础之二】常量指针和指针常量…

学习记录:ESP32控制舵机 FREERTOS BLE

控制舵机 PWM信号 PWM信号是一种周期性变化的方波信号&#xff0c;它有两个关键参数&#xff1a; 周期&#xff08;Period&#xff09;&#xff1a;一个完整的PWM信号的时间长度&#xff0c;通常用秒&#xff08;s&#xff09;或毫秒&#xff08;ms&#xff09;表示。占空比…

MQ消息队列+Lua 脚本实现异步处理下单流程

具体实现和代码可参考我以前做过的笔记&#xff1a;《黑马点评》异步秒杀优化|消息队列 回顾一下下单流程&#xff1a; 用户发起请求 会先请求Nginx,Nginx反向代理到Tomcat&#xff0c;而Tomcat中的程序&#xff0c;会进行串行工作&#xff0c; 分为以下几个操作&#xff1…

昇思25天学习打卡营第25天|基于 MindSpore 实现 BERT 对话情绪识别

基于 MindSpore 实现 BERT 对话情绪识别 模型概述 BERT&#xff08;双向编码器表征量&#xff09;是Google于2018年发布的一种先进语言模型&#xff0c;基于Transformer架构&#xff0c;具备双向上下文理解功能。BERT的预训练方法创新性地结合了两种任务&#xff1a; Masked …

高级网页爬虫开发:Scrapy和BeautifulSoup的深度整合

引言 在互联网时代&#xff0c;数据的价值日益凸显。网页爬虫作为一种自动化获取网页内容的工具&#xff0c;广泛应用于数据挖掘、市场分析、内容聚合等领域。Scrapy是一个强大的网页爬虫框架&#xff0c;而BeautifulSoup则是一个灵活的HTML和XML文档解析库。本文将探讨如何将…

凸优化笔记-基本概念

原文 文章目录 最小二乘问题 仿射affine hullaffine dimension 凸集锥集超平面和半空间单纯形整半定锥保凸性的操作透视函数 凸函数的条件1阶判定条件2阶判定条件 Epigraph 外图 m i n i m i z e f 0 ( x ) minimize\ \ \ f_0(x) minimize f0​(x) s u b j e c t t o f i ( …

Python 爬虫入门(一):从零开始学爬虫 「详细介绍」

Python 爬虫入门&#xff08;一&#xff09;&#xff1a;从零开始学爬虫 「详细介绍」 前言1.爬虫概念1.1 什么是爬虫&#xff1f;1.2 爬虫的工作原理 2. HTTP 简述2.1 什么是 HTTP&#xff1f;2.2 HTTP 请求2.3 HTTP 响应2.4 常见的 HTTP 方法 3. 网页的组成3.1 HTML3.1.1 HTM…

Debug下载与安装(Windows11)

前言 在安装配置前我们先下载一下我们需要用的文件 下载debug 百度网盘下载 下载DOSBox DOSBox 两个文件下载好后我们就开始安装和配置了 第一步&#xff1a;安装DOSBox 第二步&#xff1a;安装好后找到安装路径找到Options.bat文件并打开 第三步&#xff1a;在文件最下…

图片变色,背景方向渐变web

<!DOCTYPE html> <html lang"en"> <head> <meta charset"UTF-8"> <title>图片变色</title> <script src"03.JS\3.8JS案例加强\JQuery.js"></script> <style> .image-filter…

nvm 安装和遇到的问题

环境 win 11 安装 下载安装包 访问 https://github.com/coreybutler/nvm-windows/releases 选择需要的版本继续下载安装基本是可以下一步下一步的啦&#x1f92d; 安装 node 我这里需要16.x.x的node&#xff0c;执行以下命令 nvm install 16使用 node nvm use 16问题 …

苹果CMS V10萌芽采集插件Pro v10.7.3

苹果CMS V10萌芽采集插件Pro v10.7.3 插件下载:萌芽采集插件Pro v10.7.3.zip 使用说明: 将addons文件和static文件放到你苹果cms程序的根目录并覆盖&#xff0c; 在登录后台在应用-应用市场启用。http://你的域名/admin.php/admin/mycj/union.html