关于标准IO缓冲区的问题
关于标准IO缓冲区的问题
按照标准IO缓冲区可以分为三类:
不缓存类型:
- 一旦有数据,直接将数据写入到文件
行缓冲类型:
- 同全缓冲类型
- 遇到\n时,将数据写入文件
全缓冲类型:
- 当程序结束,将数据冲洗到文件
- 当遇见fflush(),将数据冲洗到文件
- 当文件关闭时,将数据冲洗到文件
- 当遇到读取操作,将数据冲洗到文件
- 当改变缓冲区的类型时,将数据冲洗到文件
- 当缓冲区满了,将数据冲洗到文件
对于标准输出而言,默认是行缓冲
对于标准出错而言,默认是不缓存
对于普通文件而言,默认是全缓冲
#include <stdio.h>
#include <unistd.h>
int main(int argc, char const *argv[])
{
// w+ 以读写的方式打开文件,若文件存在则清空文件数据,若文件不存在,则创建文件
FILE *fp = fopen("_a.txt", "w+");
// 将数据写入文件
fputs("123", fp);
//暂停程序不让,不让程序正常结束,观察a.txt文件内容
pause();
return 0;
}
我们能看到文件被创建,但是文件内没有内容。
我们来分析一下,我们此时是以普通文件操作,此时是默认的全缓冲,且调用了pause()函数,程序没有正常的结束,所以能猜想到此刻的内容是在缓冲区里,没有被冲洗至文件中。如果我们把pause()进行注释,在执行该程序,我们能看到我们要写入的数据出现在_a.txt文件中。这也是全缓冲类型的第一次情况,当程序结束,将数据读取到文件。
接下来我们来看一下这段代码:
#include <stdio.h>
#include <unistd.h>
int main(int argc, char const *argv[])
{
FILE *fp = fopen("_a.txt", "w+");
fputs("123", fp);
fflush(fp);
pause();
return 0;
}
印证第二种情况我们直接用冲洗函数fflush(),能看到数据成功读取到文件中。
第三种情况,在fput函数和pause函数中间,调用fclose(),关闭文件。
#include <stdio.h>
#include <unistd.h>
int main(int argc, char const *argv[])
{
FILE *fp = fopen("_a.txt", "w+");
fputs("123", fp);
fclose(fp);
pause();
return 0;
}
第四种情况,当遇到读取操作,将数据冲洗到文件。
#include <stdio.h>
#include <unistd.h>
int main(int argc, char const *argv[])
{
FILE *fp = fopen("_a.txt", "w+");
fputs("123", fp);
fgetc(fp);
pause();
return 0;
}
接下来我们看一下通过setvbuf()改变缓冲区的类型,进而对缓冲区的冲洗操作。
简单的介绍一下:setvbuf函数

这图片是我在man手册截图下来的。
int setvbuf(FILE *stream, char *buffer, int mode, size_t size)
stream -- 这是指向 FILE 对象的指针,该 FILE 对象标识了一个打开的流。
buffer -- 这是分配给用户的缓冲。如果设置为 NULL,该函数会自动分配一个指定大小的缓冲。
mode -- 这指定了文件缓冲的模式。
| _IOFBF | 全缓冲 |
|---|---|
| _IOLBF | 行缓冲 |
| _IONBF | 无缓冲 |
size --这是缓冲的大小,以字节为单位。
返回值:如果成功,则该函数返回 0,否则返回非零值。
#include <stdio.h>
#include <unistd.h>
int main(int argc, char const *argv[])
{
FILE *fp = fopen("_a.txt", "w+");
// setvbuf(fp, NULL, _IONBF, 0);
fputs("123", fp);
setvbuf(fp, NULL, _IONBF, 0);
pause();
return 0;
}
我们这里的语句是setvbuf(fp, NULL, _IONBF, 0),把普通文件默认的全缓冲,转换成无缓冲,数据在文件中有所显示,所以符合我们的第五条理论。这是为了突出我们的第五条理论,因此将该语句放置在fput语句的后面,当然如果我们在setvbuf(fp, NULL, _IONBF, 0)后面写上相同的fputs语句或者将setvbuf(fp, NULL, _IONBF, 0),放置至fopen语句后面也是会相同的效果。不过第二种情况的理解不同,此刻能成功读取数据不是因为缓冲区类型的转换,而是因为它此刻已经被定义为无缓冲,所以数据直接读取至文件中。
我们这里不妨试一试自己定义一个100字节的buf缓冲区,且在读取数据之前就将缓冲区类型转换至行缓存,观察是否能通过\n来将数据读取至文件当中去。(冲洗行缓冲)。
#include <stdio.h>
#include <unistd.h>
int main(int argc, char const *argv[])
{
FILE *fp = fopen("_a.txt", "w+");
char buf[1024];
setvbuf(fp, buf, _IOLBF, 1024);
//这里是行缓冲,如果要将数据冲洗至普通文件,注意要加\n
fputs("123\n", fp);
pause();
return 0;
}
总之,滞留在缓冲区中的数据有时被称为脏数据(dirty data),脏数据的存在代表程序操作的结果与文件真实状态不一致,若未正常冲洗这些脏数据就退出程序则有可能会造成数据丢失,我们在使用IO对数据操作时要注意对缓冲区的问题
关于标准IO缓冲区的问题的更多相关文章
- linux标准IO缓冲(apue)
为什么需要标准IO缓冲? LINUX用缓冲的地方遍地可见,不管是硬件.内核还是应用程序,内核里有页高速缓冲,内存高速缓冲,硬件更不用说的L1,L2 cache,应用程序更是多的数不清,基本写的好的软件 ...
- linux标准io的copy
---恢复内容开始--- 1.linux标准io的copy #include<stdio.h> int main(int argc,char **argv) { if(argc<3) ...
- 第十三篇:带缓冲的IO( 标准IO库 )
前言 在之前,学习了 read write 这样的不带缓冲IO函数. 而本文将讲解标准IO库中,带缓冲的IO函数. 为什么要有带缓冲IO函数 标准库提供的带缓冲IO函数是为了减少 read 和 wri ...
- C5 标准IO库:APUE 笔记
C5 :标准IO库 在第三章中,所有IO函数都是围绕文件描述符展开,文件描述符用于后续IO操作.由于文件描述符相关的操作是不带缓冲的IO,需要操作者本人指定缓冲区分配.IO长度等,对设备环境要求一定的 ...
- 为什么需要标准IO缓冲?
(转)标准I/O缓冲:全缓冲.行缓冲.无缓冲 标准I/O库提供缓冲的目的是尽可能地减少使用read和write调用的次数.它也对每个I/O流自动地进行缓冲管理,从而避免了应用程序需要考虑这一点所带来的 ...
- 带标准IO带缓存区和非标准IO 遇到fork是的情况分析
废话不多说 直接代码 #include<stdio.h> #include<sys/types.h> #include<unistd.h> #include< ...
- 带缓冲的IO( 标准IO库 )
前言 在之前,学习了 read write 这样的不带缓冲IO函数.而本文将讲解标准IO库中,带缓冲的IO函数. 为什么要有带缓冲IO函数 标准库提供的带缓冲IO函数是为了减少 read 和 writ ...
- 深究标准IO的缓存
前言 在最近看了APUE的标准IO部分之后感觉对标准IO的缓存太模糊,没有搞明白,APUE中关于缓存的部分一笔带过,没有深究缓存的实现原理,这样一本被吹上天的书为什么不讲透彻呢?今天早上爬起来赶紧找了 ...
- 【linux草鞋应用编程系列】_1_ 开篇_系统调用IO接口与标准IO接口
最近学习linux系统下的应用编程,参考书籍是那本称为神书的<Unix环境高级编程>,个人感觉神书不是写给草鞋看的,而是 写给大神看的,如果没有一定的基础那么看这本书可能会感到有些头重脚轻 ...
随机推荐
- CRM项目的整理---第一篇
CRM:cunstomer relationship management 客户管理系统 1.项目的使用者:销售 班主任 讲师 助教 2.项目的需求分析 2.1.注册 2.2.登录 2.3 ...
- Docker容器(container)详解 (转载自http://c.biancheng.net/view/3150.html)
- 思索 p5.js 的最佳实践
思索 p5.js 的最佳实践 本文写于 2020 年 12 月 18 日 p5.js 是一个 JavaScript 库,用于为艺术家.设计师提供更容易上手的创意编程. 它有着完整的一套基于 Canva ...
- 谈谈markdown
谈谈markdown 欢迎关注我的博客,️点他即可. 最近一年开始学习有关编程的内容了. 迷上代码的我开始接触到一些好玩的东西,我发现很多事情都可以由代码来完成,甚至是ppt.同学就经常说我疯掉了,连 ...
- 846. Hand of Straights - LeetCode
Question 846. Hand of Straights Solution 题目大意:打牌,判断牌是否能全部按顺子出 思路:构造一个list,存储1,2,3,4,5,6,7,8并排序,构造一个m ...
- 一文带你搞懂 Kafka 的系统架构(深度好文,值得收藏)
Kafka 简介 Kafka 是一种高吞吐.分布式.基于发布和订阅模型的消息系统,最初是由 LinkedIn 公司采用 Scala 和 java 开发的开源流处理软件平台,目前是 Apache 的开源 ...
- c++:-9
上节(c++:-8)主要学习了C++的流类库和输入输出,本节学习C++的异常处理. 异常处理 介绍 (1)异常处理的基本思想: (2)异常处理的语法: (3)举例:处理除0异常 #include &l ...
- .NET MAUI 正式版GA发布
.NET MAUI – 一个代码库,多个平台 欢迎使用 .NET 多平台应用 UI.此版本标志着我们统一 .NET 平台的多年旅程中的新里程碑.现在,您和超过 500 万其他 .NET 开发人员拥有了 ...
- Meaven静态资源过滤
` 点击查看代码 <build> <resources> <resource> <directory>src/main/java</directo ...
- PostgreSQL Array 数组类型与 FreeSql 打出一套【组合拳】
前言 PostgreSQL 是世界公认的功能最强大的开源数据库,除了基础数据类型 int4/int8/varchar/numeric/timestamp 等数据类型,还支持 int4[]/int8[] ...