关于标准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缓冲区的问题的更多相关文章

  1. linux标准IO缓冲(apue)

    为什么需要标准IO缓冲? LINUX用缓冲的地方遍地可见,不管是硬件.内核还是应用程序,内核里有页高速缓冲,内存高速缓冲,硬件更不用说的L1,L2 cache,应用程序更是多的数不清,基本写的好的软件 ...

  2. linux标准io的copy

    ---恢复内容开始--- 1.linux标准io的copy #include<stdio.h> int main(int argc,char **argv) { if(argc<3) ...

  3. 第十三篇:带缓冲的IO( 标准IO库 )

    前言 在之前,学习了 read write 这样的不带缓冲IO函数. 而本文将讲解标准IO库中,带缓冲的IO函数. 为什么要有带缓冲IO函数 标准库提供的带缓冲IO函数是为了减少 read 和 wri ...

  4. C5 标准IO库:APUE 笔记

    C5 :标准IO库 在第三章中,所有IO函数都是围绕文件描述符展开,文件描述符用于后续IO操作.由于文件描述符相关的操作是不带缓冲的IO,需要操作者本人指定缓冲区分配.IO长度等,对设备环境要求一定的 ...

  5. 为什么需要标准IO缓冲?

    (转)标准I/O缓冲:全缓冲.行缓冲.无缓冲 标准I/O库提供缓冲的目的是尽可能地减少使用read和write调用的次数.它也对每个I/O流自动地进行缓冲管理,从而避免了应用程序需要考虑这一点所带来的 ...

  6. 带标准IO带缓存区和非标准IO 遇到fork是的情况分析

    废话不多说 直接代码 #include<stdio.h> #include<sys/types.h> #include<unistd.h> #include< ...

  7. 带缓冲的IO( 标准IO库 )

    前言 在之前,学习了 read write 这样的不带缓冲IO函数.而本文将讲解标准IO库中,带缓冲的IO函数. 为什么要有带缓冲IO函数 标准库提供的带缓冲IO函数是为了减少 read 和 writ ...

  8. 深究标准IO的缓存

    前言 在最近看了APUE的标准IO部分之后感觉对标准IO的缓存太模糊,没有搞明白,APUE中关于缓存的部分一笔带过,没有深究缓存的实现原理,这样一本被吹上天的书为什么不讲透彻呢?今天早上爬起来赶紧找了 ...

  9. 【linux草鞋应用编程系列】_1_ 开篇_系统调用IO接口与标准IO接口

    最近学习linux系统下的应用编程,参考书籍是那本称为神书的<Unix环境高级编程>,个人感觉神书不是写给草鞋看的,而是 写给大神看的,如果没有一定的基础那么看这本书可能会感到有些头重脚轻 ...

随机推荐

  1. 关于Spring中的useSuffixPatternMatch

    背景 spring-boot的版本是2.1.4.RELEASE,spring的版本是5.1.6.RELEASE 一个例子如下: @Configuration @Import(WebMvcAutoCon ...

  2. Hadoop——API操作

    代码示例: package com.atguigu.hdfs; import org.apache.hadoop.conf.Configuration; import org.apache.hadoo ...

  3. 在linux上开启酸酸乳,未完待续

    在服务器调试深度学习环境的时候总需要下载conda的包,一直以来都觉得是因为国内访问慢,于是想在服务器上开 ,或者ssr.由于过去用ssr多一些,于是想了解ssr on linux. 1.首先win1 ...

  4. dotnet-cnblog-tool 图片上传失败问题

    dotnet-cnblog-tools 这个工具是将本地的 Markdown 文件转换为 可以上传到 cnblog 的格式,并且会将图片自动上传到 cnblog 的图床. 具体可以参考这篇文章: cn ...

  5. MySQL数据库5

    内容概要 pyhton操作MySQL SQL注入问题 修改表SQL语句补充 视图.触发器.储存过程 事务 流程控制 函数 索引与慢查询优化 内容详情 pyhton操作MySQL python中支持操作 ...

  6. Cabloy-CMS中区块的开发与效果

    关于区块 Cabloy-CMS引入了区块的概念,通过区块可以快速向文章添加各种类型的内容,比如:插入一个地图子页面.插入一首音乐,等等 Cabloy-CMS中的区块可以类比于Wordpress古腾堡编 ...

  7. 全新升级的AOP框架Dora.Interception[1]: 编程体验

    多年之前利用IL Emit写了一个名为Dora.Interception(github地址,觉得不错不妨给一颗星)的AOP框架.前几天利用Roslyn的Source Generator对自己为公司写的 ...

  8. 几种常见的DoS攻击

    DoS为Denial of Service的简称,意思是拒绝服务.DoS攻击是一种使被攻击者无法正常提供服务的攻击.常见的攻击方式有以下几种类型:   LAND Local Area Network ...

  9. SAP Display picture

    program sap_picture_demo. set screen 200. TYPE-POOLS cndp. ***************************************** ...

  10. Spring jdbctemplate和事务管理器

    内部bean 对象结构: @Autowiredprivate IAccountService accountService; @Service("accountService")@ ...