news 2026/10/21 16:13:58

标准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/10/17 0:23:29

Dify平台的API文档自动生成与维护实践

Dify平台的API文档自动生成与维护实践 在AI应用加速落地企业生产环境的今天&#xff0c;一个现实问题日益凸显&#xff1a;即便模型能力强大&#xff0c;若接口混乱、文档滞后&#xff0c;依然难以被系统集成。许多团队经历过这样的场景——算法工程师调通了RAG流程&#xff0c…

作者头像 李华
网站建设 2026/10/21 13:27:28

元组、列表、字符串、字典定义及切割

一、元组1.定义元组是 Python 中的一种数据类型&#xff0c;表示一组有序的元素。元组是不可变的&#xff0c;即创建之后无法修改其中的元素&#xff08;不支持增、删、改操作&#xff09;。元组通常用于存储多个元素&#xff0c;但元素不需要改变的场景。(1) 元组的创建方式&a…

作者头像 李华
网站建设 2026/10/19 7:15:48

小红书数据采集神器:Python自动化工具xhs深度解析

小红书数据采集神器&#xff1a;Python自动化工具xhs深度解析 【免费下载链接】xhs 基于小红书 Web 端进行的请求封装。https://reajason.github.io/xhs/ 项目地址: https://gitcode.com/gh_mirrors/xh/xhs 还在为获取小红书公开数据而烦恼吗&#xff1f;xhs这个Python工…

作者头像 李华
网站建设 2026/10/9 8:28:57

5个简单步骤彻底释放拯救者笔记本性能:告别卡顿的终极方案

5个简单步骤彻底释放拯救者笔记本性能&#xff1a;告别卡顿的终极方案 【免费下载链接】LenovoLegionToolkit Lightweight Lenovo Vantage and Hotkeys replacement for Lenovo Legion laptops. 项目地址: https://gitcode.com/gh_mirrors/le/LenovoLegionToolkit 还在为…

作者头像 李华
网站建设 2026/10/15 21:23:56

5分钟掌握md2pptx:让Markdown一键转PPT不再是梦想

5分钟掌握md2pptx&#xff1a;让Markdown一键转PPT不再是梦想 【免费下载链接】md2pptx Markdown To PowerPoint converter 项目地址: https://gitcode.com/gh_mirrors/md/md2pptx 还在为制作演示文稿而头疼吗&#xff1f;每次打开PowerPoint都要花费大量时间调整格式、…

作者头像 李华