Standard IO

news2024/11/26 4:33:27

为了提高可移植性,将通用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 NULL

int 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); //只会打印123
    puts("");
    fwrite((const void*)buf,1,10,stdout); //打印123\0 456
    return 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.coloradmin.cn/o/2221126.html

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

相关文章

element plus e-table表格中使用多选,当翻页时已选中的数据丢失

摘要&#xff1a; 点击第一页选中两个&#xff0c;再选择第二页&#xff0c;选中&#xff0c;回到第一页&#xff0c;之前选中的要保留&#xff01; element ui table 解决办法&#xff1a; :row-key“getRowKeys” &#xff08;写在el-table中&#xff09; methods中声明 ge…

多一DY4100数字式接地电阻测试仪使用测量方法

接地电阻二线法测量步骤 1、找出一套简易测试线&#xff0c;一根红色两插头线和一根短绿线&#xff1b; 2、找出一根辅助地钉&#xff0c;距离被测接地桩/扁铁约五米远整根打下去&#xff1b; 3、绿线插头接仪器E孔&#xff08;绿色孔&#xff09;&#xff0c;夹子夹需测的接…

ArcGIS002:软件自定义设置

摘要&#xff1a;本文详细介绍安装arcgis10.2后软件自定义设置内容&#xff0c;包括工具条的启用、扩展模块的启用、如何加载项管理器、快捷键设置、样式管理器的使用以及软件常规设置。 一、工具条的启用 依次点击菜单栏【自定义】->【工具条】&#xff0c;根据工作需求勾…

医院信息化与智能化系统(5)

医院信息化与智能化系统(5) 这里只描述对应过程&#xff0c;和可能遇到的问题及解决办法以及对应的参考链接&#xff0c;并不会直接每一步详细配置 如果你想通过文字描述或代码画流程图&#xff0c;可以试试PlantUML&#xff0c;告诉GPT你的文件结构&#xff0c;让他给你对应的…

【漏洞修复/安全补丁】5.4之前版本通过api/products接口进行sql注入的问题

5.4之前版本&#xff0c;会使用api/products接口的selectId参数进行sql注入 修复办法 1、修改crmeb/app/api/controller/v1/store/StoreProductController.php文件中的lst方法里面的接收参数&#xff0c;修改成下图 如果你的版本没有coupon_category_id参数的话&#xff0c;…

No.19 笔记 | WEB安全 - 任意文件操作详解 part 1

1. 任意文件上传漏洞基础 什么是文件上传功能? 在网站和应用中,我们经常会看到允许用户上传文件的功能,比如: 更换头像:让用户上传自己的照片作为头像发布图片:在社交媒体或论坛上传图片提交文档:在办公系统中上传Word、Excel等文档 这些都是常见的文件上传功能。 任意文…

Kettle9.4支持Clickhouse数据源插件开发以及性能测试

前言 最近业务这边有个指标需要用到大数据这边的列式数据库进行处理&#xff0c;由于kettle不支持clickhouse数据源驱动&#xff0c;这里查了一下网上的相关资料&#xff0c;发现了一些别人开发好的驱动包&#xff0c;下载下来后使用效果不尽人意。总结下来有以下几个问题&…

重生之“我打数据结构,真的假的?”--1.顺序表(无习题)

C语言中的顺序表详细总结 1. 概述 顺序表&#xff08;Sequential List&#xff09;是一种线性数据结构&#xff0c;用于存储具有相同数据类型的一组元素。顺序表采用一段连续的存储空间&#xff0c;使用数组来实现&#xff0c;能够高效地支持随机访问操作。在 C 语言中&#…

基于ssm的校园车辆管理系统的设计与实现

文未可获取一份本项目的java源码和数据库参考。 一、选题背景与意义 &#xff08;一&#xff09;选题背景 自改革开放以来&#xff0c;国家开始加大力度对高等校园进行投入&#xff0c;深化了教育体制的改革&#xff0c;全国许多高等校园应运而生&#xff0c;越来越多的孩子走…

C++ —— 《模板进阶详解》,typedef和class的区别以及用法,非类型模板参数,模板的特化,模板的分离编译

目录 1.非类型模板参数 2.模板特化 2.1 概念 2.2 函数模板特化 2.3 类模板特化 2.3.1 全特化 2.3.2 偏特化 3 模板分离编译 3.1 什么是分离编译 3.2 模板的分离编译 4.模板总结 在讲解模板进阶之前&#xff0c;我想先简单单独聊聊class和typename的用法 我们在平时…

Mac使用Git仓库上传文件夹方法

环境&#xff1a;mac 仓库&#xff1a;GitLink Q: 首先我们先了解到&#xff0c;远程下载&#xff08;用ssh&#xff09;仓库会默认下载到电脑的哪里呢&#xff1f; A: 如下图&#xff0c;路径为/Users/bb&#xff0c;&#xff08;bb是我的用户名&#xff09; 那么我们在将a文…

筑牢理性防线,“卡游启智,理性护航”青少年健康消费倡议发布

新华网北京10月22日电&#xff08;记者周靖杰&#xff09;10月21日&#xff0c;国内针对青少年卡牌盲盒消费的倡议在京发布。 “卡游启智&#xff0c;理性护航”青少年健康消费倡议在京正式发布 近年来&#xff0c;卡牌盲盒在青少年中悄然流行&#xff0c;买卡、拆包、集卡成为…

临时配置linux Bridge网桥

Linux Bridge&#xff08;网桥&#xff09;是用纯软件实现的虚拟交换机&#xff0c;有着和物理交换机相同的功能&#xff0c;例如二层交换&#xff0c;MAC地址学习等。因此我们可以把tun/tap&#xff0c;veth pair等设备绑定到网桥上&#xff0c;就像是把设备连接到物理交换机上…

数据可视化示例

用eclipse软件 java 代码&#xff1a; <!DOCTYPE html> <html> <head> <meta charset"UTF-8"> <!-- 引入ECharts脚本&#xfe63;-> <script src"js/echarts.js"></script> <title&#xff1e;网格…

红日靶场(三)1、环境介绍及环境搭建

1、靶场介绍 红日靶场03是一个用于安全测试和渗透测试的虚拟化环境&#xff0c;可以帮助用户通过模拟攻击和防御场景来提升网络安全技能。该靶场包含了多个虚拟机和网络配置&#xff0c;用户可以在其中进行各种安全测试活动&#xff0c;如信息收集、漏洞利用、权限提升等。 2…

Java项目-基于Springboot的高校党务系统项目(源码+说明).zip

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

ACL访问控制

要求&#xff1a; PC1与PC2不能通信。PC1可以和PC3通信。PC2可以和PC3通信。 1. VLAN配置 根据拓扑图的连接&#xff0c;PC1、PC2、PC3属于不同的VLAN。我们需要确保交换机上的端口已经正确划分到不同的VLAN。假设交换机接口的VLAN配置已经完成&#xff08;其他博文有)&…

在VMware中安装LInux

1.打开VMware选择新建虚拟机 2.这里建议初学者选择“典型&#xff08;推荐&#xff09;”。 3.已提前准备好 Linux 系统的映像文件&#xff08;.iso 文件&#xff09;&#xff0c;此处可选择“安装程序光盘映像文件”&#xff0c;并通过“浏览”按钮找到要安装 Linux 系统的 i…

“金秋敬老月 浓浓孝老情”2024中益孝行大爱进万家敬老月公益活动走进涿州

为贯彻实施积极应对人口老龄化国家战略&#xff0c;弘扬中华民族孝亲敬老传统美德&#xff0c;10月22日&#xff0c;中益老龄事业发展中心和涿州市东城坊镇人民政府在安享城养老院联合开展“金秋敬老月&#xff0c;浓浓孝老情”2024中益孝行大爱进万家敬老月公益活动。中益老龄…

android openGL ES详解——混合

一、混合概念 混合是一种常用的技巧&#xff0c;通常可以用来实现半透明。但其实它也是十分灵活的&#xff0c;你可以通过不同的设置得到不同的混合结果&#xff0c;产生一些有趣或者奇怪的图象。混合是什么呢&#xff1f;混合就是把两种颜色混在一起。具体一点&#xff0c;就…