Standard IO

为了提高可移植性,将通用IO接口经过再封装就形成了标准IO,标准IO不仅适用于Unix环境,也兼容非Unix环境,这也是为什么说我们应该尽可能的使用标准IO,通用IO通过文件描述符fd来与文件交互,为了以示区分,标准IO定义了流的概念作为与文件交互的入口

文件流

文件流是一个FILE*类型的变量,FILE是C标准定义的一个结构体,内部维护了进程对于文件的各种信息,其中就包括了文件描述符,文件流对于标准IO非常重要,几乎所有的标准IO接口都需要使用到文件流,就如同几乎所有的通用IO需要用到文件描述符一样。

标准流

标准流是比较特殊的文件流,分别是标准输出、标准输入和标准错误,这三个文件流在程序启动时就会默认打开,这也是为什么我们在包含头文件之后可以直接进行scanf和printf的原因(回想一下,你使用scanf和printf时几乎不需要接触流这个概念吧)

标准中分别用stdin、stdout、stderr三个宏常量来表示标准流

缓冲区

标准IO相比于通用IO最显著的特点就是缓冲区,这里的缓冲区是用户缓冲区,缓冲机制使得标准IO真实读写磁盘的次数大大减少从而大大提高了效率

缓冲区策略

  • 页缓冲:缓冲区中的数据超过一页大小(4096bytes)时进行一次落盘
  • 行缓冲:遇到换行符进行一次落盘(超过一页也会落盘)
  • 不缓冲:有数据就落盘

默认情况下 磁盘文件采用页缓冲;标准输入输出文件采用行缓冲;标准错误文件不缓冲

可以通过setbuf和setvbuf显式设置对应文件流的缓冲策略

void setbuf(FILE* fp,char* buf);
int setvbuf(FILE* fp,char* buf,int mode,size_t size); //return no-zero if error

setbuf可以决定是否采用缓冲策略

​ buf为空时不缓冲,否则采用行缓冲或页缓冲(根据文件特点),buf若非空长度必须指向长度为BUFSIZE的缓冲区(C标准提供的常量)

setvbuf可以更精确设置缓冲策略

通过buf和size的配合,可以灵活的设置大小为size的缓冲区,mode的取值决定缓冲策略(如果buf为空将由系统自动分配用户缓冲区)

mode取值

  • _IOFBF 页缓冲
  • _IOLBF 行缓冲
  • _IONBF 不缓冲

强制刷盘

int fllush(FILE* fp);
//return no-zero if error

调用fllush可以暂时无视缓冲区策略,直接对缓冲区中的数据进行刷盘操作

文件流操作

打开流

FILE* fopen(const char* pathname,const char* type);
FILE* freopen(const char* pathname,const char* type,FILE* fp);
FILE* fdopen(int fd,const char* type);
//return NULL if error

freopen可以复用FILE*变量,在一个已经打开的文件流上再次打开一个文件流,原先打开的文件流会先关闭

由于fopen一般只用于打开普通文件,对于一些只能用open打开的文件可以先获取其文件描述符,再通过fdopen将文件描述符与一个流结合,后续以同一的文件流进行读写

打开模式

在这里插入图片描述

b表示二进制模式打开

关闭流

int fclose(FILE* fp);
//return no-zero if error

读写流

字符读写

int getc(FILE* fp);
int fgetc(FILE* fp);
int getchar();
//return ASCII if succeed,or EOF(-1)int putc(int c,FILE* fp);
int fputc(int c,DILE* fp);
int putchar(int c);
//return ASCII if succeed,or EOF

getc和fgetc等价

getchar用于从标准输入流读取

putc和fputc等价

putchar用于打印至标准输出流

行读写

char* fgets(char* buf,int n,FILE* fp);
//return buf if succeed,or NULLint fputs(const char* str,FILE* fp);
int puts(const char* str);
//return no-zero if succeed ,or NULL

对于 fgets,必须指定缓冲的长度n。它一直读到下一个换行符为止,但是不超过 n-1个字符,读入的字符被送入缓冲区。该缓冲区以**\0结尾**。如若该行包括最后一个换行符的字符数超过 n-1,则 fgets 只返回一个不完整的行,但是,缓冲区总是以 -\0结尾。对 fgets的下一次调用会继续读该行

eg:

#include <stdio.h>int main()
{char buf[4]={0};while(1){fgets(buf,4,stdin);puts(buf); //这里使用puts的自动换行功能可以更明显看出fgets对于一次输入分2次完成}return 0;
}
多用fputs而非puts

puts直接在标准输出上显示内容,它会自动添加换行符,但是C语言中大多数输出没有这种特性,fputs不会自动添加换行符,更有C风格

结束与错误

int ferror(FILE* fp);
int feof(FILE* fp);void clearerr(FILE* fp);

如果文件出错ferror返回非0值;如果文件读完则feof返回非0值

FILE结构中维护了出错标志和结束标志,当我们使用ferror或feof判断返回EOF的原因并进行问题处理后,一般希望将这2位归置,可以通过clearerr(FILE fp)*方法

二进制读写

size_t fread(void* ptr,size_t size,size_t n,FILE* fp);
size_t fwrite(const void* ptr,size_t size,size_t n,FILE* fp);
//返回实际读写的个数(单位为size)

非二进制读写都规定了\0作为结束符,二进制读写则没有规定结束符,它严格地按照指定读取个数(n)来读取数据,n的单位不是字节,而是第二个参数size

eg1:fwrite和fputs

int main()
{char buf[BUFSIZ]="123\0 456";fputs((const char*)buf,stdout); //只会打印123puts("");fwrite((const void*)buf,1,10,stdout); //打印123\0 456return 0;
}

eg2:二进制读写结构

typedef struct student{int id;char name[16];
}student;
int main()
{student s[3]={{1,"zhangsan "},{2,"lisi "},{3,"wangwu "}};fwrite((const void*)s,sizeof(student),3,stdout);return 0;
}

定位流

long ftell(FILE* fp);
int fseek(FILE* fp,long offset,int whence);
void rewind(FILE* fp);//回到起始位置

格式读写

int printf(const char* format,...);
int fprintf(FILE* fp,const char* format,...);
int snprintf(char* buf,size_t n,const char* format,...);//格式化字符串
//返回输出字符数,出错则为负值
int scanf(const char* format,...);
int fscanf(FILE* fp,const char* format,...);
int sscanf(const char* buf,const char* format,...);
//返回输入字符数,出错则为负值

格式化写占位符

在这里插入图片描述

格式化读占位符

在这里插入图片描述

内存流

所谓内存流就是不在磁盘上开辟空间,而是在内存上开辟空间存放数据,这些数据都是临时性的,因为内存没有持久化的功能,fmemopen使得用户可以像读写文件一样读写内存

FILE* fmemopen(void* buf,size_t size,const char* type);

内存流的打开模式稍显特殊。

  • 以追加写方式打开内存流时,当前文件位置设为缓冲区中的第一个\0字节。如果缓冲区中不存在\0字节,则当前位置就设为缓冲区结尾的后一个字节。因此内存流并不适合存储二进制数据(二进制数据在数据尾端之前就可能包含多个 null 字节)。

  • 如果buf参数是空指针,打开流进行读或者写都没有任何意义。因为在这种情况下缓冲区是通过 fmemopen进行分配的,没有办法找到缓冲区的地址,只写方式打开流意味着无法读取已写入的数据,同样,以读方式打开流意味着只能读取那些我们无法写入的缓冲区中的数据。

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

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

相关文章

DCGAN的原理(附代码解读)

学习DCGAN之前需要了解一下转置卷积 可以参考学DCGAN对抗网络之前--转置卷积(附代码解读)-CSDN博客 1.DCGAN对于GAN的改进之处 网络架构的优化&#xff1a; DCGAN在生成器和判别器中明确使用了卷积层和卷积转置层&#xff08;也称为反卷积层或分数阶卷积层&#xff09;。这一…

『 Linux 』HTTPS

文章目录 HTTPS协议密钥加密的原因加密方式数据指纹网络通信加密方案及短板CA认证CA证书的细节以及如何保证服务端公钥的安全性和数据完整性 CA认证后对称加密与非对称加密配合使用的安全性中间人的攻击方式 HTTPS协议 HTTPS协议并不是一个独立的协议,其是一种以HTTP协议为基础…

基于SSM的洗浴中心管理系统的设计与实现

文未可获取一份本项目的java源码和数据库参考。 方案设计&#xff08;研究的基本内容&#xff0c;拟解决的基本问题&#xff0c;研究步骤、方法及措施&#xff09;&#xff1a; 研究的基本内容&#xff1a;根据当今社会市场所需&#xff0c;通过对比多家洗浴中心进行深入细致的…

第二十九篇:图解TCP三次握手,看过不会忘,从底层说清楚,TCP系列四

⼀开始&#xff0c;客户端和服务端都处于 CLOSED 状态。先是服务端主动监听某个端⼝&#xff0c;处于 LISTEN 状态。 接下来这部分内容的介绍将影响你能不能彻底理解了TCP的三次握手。 一、划重点&#xff1a;只有服务端启动了端口监听&#xff0c;客户端TCP握手才能建立连接&…

ubuntu系统库和Anaconda库冲突问题

之前安装opencv时没出现过这种问题,自从安装Anaconda后就总遇到问题。记录下自己的解决过程。 目录 第一步 第二步 第三步 安装opencv时出现以下问题: /usr/bin/ld: /lib/x86_64-linux-gnu/libwayland-client.so.0: undefined reference to `ffi_prep_cif@LIBFFI_BASE_7.…

若依框架篇-若依集成 X-File-Storage 框架(实现图片上传阿里云 OSS 服务器)、EasyExcel 框架(实现 Excel 数据批量导入功能)

&#x1f525;博客主页&#xff1a; 【小扳_-CSDN博客】 ❤感谢大家点赞&#x1f44d;收藏⭐评论✍ 文章目录 1.0 实现使用 Excel 文件批量导入 1.1 导入功能的前端具体实现 1.2 导入功能的后端具体实现 1.3 使用 EasyExcel 框架实现 Excel 读、写功能 1.4 将 Easy Excel 集成到…

路径跟踪之导航向量场(二)——三维导航向量场

上一期文章介绍了二维平面下的导航向量场计算方法&#xff0c;本期文章将介绍三维空间中&#xff0c;导航向量场及扩展。 本文主要介绍论文[1]中提出的一种基于导航向量场的航迹跟踪算法。此外&#xff0c;虽然本文以三维航迹为例进行介绍&#xff0c;但该方法可非常方便的拓展…

智能优化算法-生物地理学算法(BBO)(附源码)

目录 1.内容介绍 2.部分代码 3.实验结果 4.内容获取 1.内容介绍 生物地理学优化算法 (Biogeography-Based Optimization, BBO) 是一种基于生物地理学原理的元启发式优化算法&#xff0c;由Dan Simon于2008年提出。BBO通过模拟物种在不同栖息地之间的迁移过程来搜索最优解&…

【JavaEE】——四次挥手,TCP状态转换,滑动窗口,流量控制

阿华代码&#xff0c;不是逆风&#xff0c;就是我疯 你们的点赞收藏是我前进最大的动力&#xff01;&#xff01; 希望本文内容能够帮助到你&#xff01;&#xff01; 目录 一&#xff1a;断开连接的本质 二&#xff1a;四次挥手 1&#xff1a;FIN 2&#xff1a;过程梳理 …

新时代AI桌宠:XGO Rider让你的办公室瞬间高大上

​ XGO Rider Luwu 智能打造了桌面双轮足式机器人 XGO Rider&#xff0c;这款全球首创的轮腿式桌面AI机器人&#xff0c;正在悄然改变我们的办公环境。它不仅是一个高科技玩具&#xff0c;更是一个能大幅提升工作效率和办公室科技感的智能助手。 XGO Rider 新时代“桌宠” micr…

基于java+springboot的宇宙动漫网站

文章目录 前言项目介绍技术介绍功能介绍核心代码数据库参考 系统效果图 前言 文章底部名片&#xff0c;获取项目的完整演示视频&#xff0c;免费解答技术疑问 项目介绍 本系统为用户而设计制作宇宙动漫网站&#xff0c;旨在实现宇宙动漫智能化、现代化管理。本宇宙动漫管理自…

爬虫——scrapy的基本使用

一&#xff0c;scrapy的概念和流程 1. scrapy的概念 Scrapy是一个Python编写的开源网络爬虫框架。它是一个被设计用于爬取网络数据、提取结构性数据的框架。 框架就是把之前简单的操作抽象成一套系统&#xff0c;这样我们在使用框架的时候&#xff0c;它会自动的帮我们完成很…

【数据结构与算法】之有序链表去重(保留重复元素)

目录 1.问题描述 2.思路讲解 3.Java 代码实现 4.代码解释 5.复杂度分析 6.其它方法 6.1 递归实现 6.2 双指针 7.总结 相关教程&#xff1a; 有序链表去重&#xff08;不保留重复元素&#xff09; 数据结构之链表详解 递归详解 1.问题描述 给定一个已排序的单链表…

Java可以做人工智能吗-回答是当然可以

Java在人工智能应用开发中的角色与优势 人工智能主要分为两个部分&#xff1a;一个是做底层的大语言模型的训练&#xff0c;另一个是基于大模型进行业务应用。Java最适合做的就是第二个方面&#xff0c;即基于大模型构建业务应用。由于过去大量的企业级应用都是使用Java开发的…

网络服务请求流程简单理解

网络流程&#xff1a; DNS负责将域名解析为IP地址&#xff0c;ALB可以在多个服务实例之间分配流量&#xff0c;APISIX作为API网关处理更细粒度的流量管理&#xff0c;Service在Kubernetes中为Pod提供稳定的访问入口&#xff0c;而Kubernetes则负责整个应用的部署、扩展和运维。…

Java项目-基于springboot框架的逍遥大药房管理系统项目实战(附源码+文档)

作者&#xff1a;计算机学长阿伟 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、ElementUI等&#xff0c;“文末源码”。 开发运行环境 开发语言&#xff1a;Java数据库&#xff1a;MySQL技术&#xff1a;SpringBoot、Vue、Mybaits Plus、ELementUI工具&#xff1a;IDEA/…

【UML】一个UML学习的还不错的几个帖子

https://segmentfault.com/a/1190000042775634 寂然解读设计模式 - UML类图&类的六大关系-阿里云开发者社区

最佳简历--JAVA程序员的项目经验如何写

小熊学Java全能学习+面试指南:https://www.javaxiaobear.cn 首先你要明确,你能干什么,包括你自己编写的专业技能,到底会不会,怎么运用到技术上的? 1、你能干什么? 你能干什么,其实就展现你的能力,这是简历中最重要的部分,你需要证明前面说的你会的东东; 这就有点…

【前端】如何制作一个自己的网页(14)

当我们还需要对网页中的内容进行局部样式的修改。这时候&#xff0c;就需要用到HTML中的重要元素&#xff1a;span。 span是一个行内元素&#xff0c;可以对HTML文档中的内容进行局部布局。 如图&#xff0c;我们给标题和段落元素的部分内容设置了各种样式。 接下来&#xff0…