news 2026/6/10 12:59:53

标准IO之流与缓冲

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
标准IO之流与缓冲

文章目录

  • 流(FILE)
    • 文本流与二进制流
    • 流的缓冲类型
      • 无缓冲
      • 行缓冲
      • 全缓冲
      • 修改缓冲类型
  • 标准I/O 由ANSI C标准定义,主流操作系统上都实现了C库
  • 标准I/O通过缓冲机制减少系统调用,实现更高的效率

标准IO是C函数库的常见IO操作接口(对操作系统提供的系统调用进行封装,进一步降低与硬件的耦合),提供了缓冲机制,减少触发系统调用次数,实现了更高的效率

- fopen 函数是由封装 open 函数实现 - fclose 函数是由封装 close 函数实现 - fread 函数是由封装 read 函数实现 - fwrite 函数是由封装 write 函数实现 - fseek 函数是由封装 lseek 函数实现
  • 标准IO用一个结构体类型来存放打开的文件的相关信息,所有操作都是围绕FILE来进行
  • 查看FILE结构的定义:
    • vi /usr/include/stdio.h
    • vi /usr/include/bits/types/struct_FILE.h

  • 文件IO和标准IO对比

流(FILE)

  • 标准IO用一个结构体类型来存放打开的文件的相关信息
  • 标准I/O的所有操作都是围绕FILE来进行
  • FILE又被称为流(stream),文本流/二进制流

文本流与二进制流

  • 文本流:数值以字符形式,每一个字符都是一个字节,对应ASCII码值。文本流中的数据可以显示和打印出来,都是用户可以读懂的信息
  • 二进制流:流中的数据是按照二进制编码的方式(值的方式)来存放文件。二进制数据也可在屏幕上显示,但其内容无法读懂
  • 二进制流比文本流更节省空间,且不用对换行符进行转换,这样可以大大加快流的速度,提高效率,二进制流没有行长度的限制,也可以包含空字符(NULL)。
  • 因此,对于含有大量数据信息的数字流,可以采用二进制流的方式;对于含有大量字符信息的流,则采用文本流的方式

流的缓冲类型

  • 标准I/O预定义3个流,程序运行时自动打开
名称文件描述符(值)常量缓冲类型
标准输入流0STDIN_FILENOstdin通常是行缓冲
标准输出流1STDOUT_FILENOstdout当连接到终端时,通常是行缓冲
标准错误流2STDERR_FILENOstderr默认是无缓冲,立即输出

无缓冲

  • 数据直接写入文件,流不进行缓冲
#include<stdio.h>#include<unistd.h>intmain(intargc,constchar*argv[]){perror("aaaa");#if0while(1){sleep(1);}#endifreturn0;}
  • 程序正常结束会主动刷新缓冲区

行缓冲

  • 当在输入和输出中遇到换行符(‘\n’)时,会自动触发刷新
  • 当缓冲区达到其容量限制时,会自动触发刷新
  • 当 main() 函数返回或调用 exit() 时,所有缓冲区的数据都会被刷新
  • 当流和一个终端关联时,典型的行缓冲
    • printf("Enter name: "); // 可能不会立即显示
    • scanf("%s", name); // 读取前会刷新 stdout
#include<stdio.h>#include<unistd.h>intmain(intargc,char*argv[]){inti=0;#if0do{printf("a");i++;}while(i<100);#else//1024do{printf("a");i++;}while(i<1025);#endifsleep(10);return0;}
  • \n是换行字符,printf支持的是行缓冲,加上\n刷新了行缓冲,实现输出
  • 不同的环境是不一样的大小,这里标准输出的行缓冲是1024个字节。

全缓冲

  • 当流的缓冲区无数据或无空间触发刷新
  • 当 main() 函数返回或调用 exit() 时,所有缓冲区的数据都会被刷新
  • 关闭文件或程序正常结束触发刷新

  • 全缓冲大小和系统有关系,在Ubuntu 14.04 32位系统、Ubuntu 22.04 64位系统测试是4096字节
#include<stdio.h>#include<unistd.h>intmain(intargc,char*argv[]){FILE*fd=fopen("a.txt","a+");fprintf(fd,"a");//读、写缓冲区大小printf("%d ",fd->_IO_buf_end-fd->_IO_buf_base);// 4096inti=0;do{fprintf(fd,"a");i++;}while(i<4098);//测试写指针偏移量printf("%d",fd->_IO_write_ptr-fd->_IO_write_base);// 3sleep(5);return0;}

修改缓冲类型

  • 通过setbuf、setvbuf函数修改缓冲类型
  • setbuf(stdout, NULL);关闭缓冲,将缓冲策略修改为无缓冲
#include<stdio.h>#include<unistd.h>intmain(intargc,char*argv[]){printf("a");sleep(5);//a是行缓冲,原则是不输出的,这时关闭缓冲setbuf(stdout,NULL);//模式是无缓冲后,先把缓冲中的a刷了出来,b再立马输出printf("b");sleep(5);return0;}
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/26 15:47:23

大麦网抢票终极指南:轻松实现演唱会门票自动购买

大麦网抢票终极指南&#xff1a;轻松实现演唱会门票自动购买 【免费下载链接】DamaiHelper 大麦网演唱会演出抢票脚本。 项目地址: https://gitcode.com/gh_mirrors/dama/DamaiHelper 还在为抢不到心仪的演唱会门票而烦恼吗&#xff1f;大麦网抢票脚本正是你需要的解决方…

作者头像 李华
网站建设 2026/6/5 9:12:34

一键备份青春记忆:GetQzonehistory完整数据导出实战指南

一键备份青春记忆&#xff1a;GetQzonehistory完整数据导出实战指南 【免费下载链接】GetQzonehistory 获取QQ空间发布的历史说说 项目地址: https://gitcode.com/GitHub_Trending/ge/GetQzonehistory 在数字时代&#xff0c;我们的青春记忆被分散存储在各类社交平台中&…

作者头像 李华
网站建设 2026/6/10 11:03:01

Kali配置一句话木马

打开kali&#xff0c;启动apache服务 访问kali的ip 然后编写一句话木马&#xff1a; 在kali中打开文件系统按照路径找到 /var/www/html文件夹 以root身份打开&#xff0c;创建文件shell.php&#xff0c;在该文件中输入一句话木马&#xff1a; 保存后关闭页面&#xff0c;在浏…

作者头像 李华
网站建设 2026/6/3 1:05:01

Dify平台的财务预测建模能力初探

Dify平台的财务预测建模能力初探 在企业数字化转型不断加速的今天&#xff0c;财务部门正面临前所未有的挑战&#xff1a;不仅要应对海量数据的处理压力&#xff0c;还要在极短时间内提供准确、可解释的预测结果。传统的Excel模型和静态报表已难以满足管理层对“实时洞察”的需…

作者头像 李华
网站建设 2026/5/20 16:08:51

终极游戏模组管理指南:一站式解决方案

终极游戏模组管理指南&#xff1a;一站式解决方案 【免费下载链接】XXMI-Launcher Modding platform for GI, HSR, WW and ZZZ 项目地址: https://gitcode.com/gh_mirrors/xx/XXMI-Launcher 还在为复杂的游戏模组安装而烦恼&#xff1f;XXMI启动器为您提供完整的一站式游…

作者头像 李华