一、标准IO的缓冲区
标准 I/O 中的缓冲区是C语言标准库为优化文件读写效率设计的内存机制,本质上就是一段由FILE结构体管理的内存空间;通过临时存储数据、批量处理,可以减少硬件IO(如磁盘、终端)的交互次数,提升程序效率。
缓冲策略:标准 I/O 中有行缓冲、全缓冲、无缓冲三种,适配不同的场景,支持手动修改:
- 行缓冲:默认用于终端设备(如stdout、stdin),Linux系统中行缓冲的大小为1024(1KB);
- 全缓冲:默认用于文件(如 .txt),Linux系统中全缓冲大小通常是4096(4KB);
- 无缓冲:不使用临时内存暂存,数据直接写入硬件(如stderr);无缓冲区的大小为0;
//求行缓存区的大小------行缓存区默认用于终端设备
//注意:程序一开始运行并没有把数据写入缓存区中,所以没有给行缓存区分配实际内存,为0
printf("行缓存区的大小:%ld\n",stdout->_IO_buf_end-stdout->_IO_buf_base);
printf("hello\n");
//运行printf("hello")后,会将数据写入行缓存区,所以内存为1024
printf("行缓存区的大小:%ld\n",stdout->_IO_buf_end-stdout->_IO_buf_base);
//求全缓存区内存大小------全缓存区默认文件设备
FILE *fp=NULL;
if(NULL == (fp=fopen("test.c","r"))){
perror("文件打开失败");
return -1;
}
printf("文件打开成功\n");
//从文件中读取数据
int ch=0;
ch=fgetc(fp);
printf("ch:%c\n",ch);
//求全缓存区的大小
printf("全缓存区的大小:%ld\n",fp->_IO_buf_end-fp->_IO_buf_base);
//关闭文件
fclose(fp);
//求无缓存区的大小------无缓存:没有缓存区直接写入硬件
printf("无缓存区的大小:%ld\n",stderr->_IO_buf_end-stderr->_IO_buf_base);
二、缓冲区刷新时机
(一)行缓冲刷新时机
- 遇到换行符 \n 会刷新缓冲区;
- 程序正常结束会刷新缓冲区;
- 当文件关闭时会刷新缓冲区;
- 在输入和输出发生切换时会刷新缓冲区;
- 缓冲区写满(未到换行符)会刷新缓冲区;
- 主动调用fflush函数会强制刷新缓冲区;
fflush函数:所需头文件 #include <stdio.h> ,原型:int fflush(FILE *stream); 将指定流(stream)缓冲区中尚未写入的内容,强制写入到对应的输出设备(如文件、终端等)中,成功则返回0,刷新了流缓冲区;失败则返回EOF,并将errno设置为具体的错误类型
(二)全缓冲刷新时机
注意:全缓存不会遇到换行符 \n 会刷新缓冲区。
- 程序正常结束会刷新缓冲区;
- 当文件关闭时会刷新缓冲区;
- 在输入和输出发生切换时会刷新缓冲区;
- 缓冲区写满(未到换行符)会刷新缓冲区;
- 主动调用fflush函数会强制刷新缓冲区;
三、手动设置缓冲区
(一)sleep函数
所需头文件:#include <unistd.h>
原型:unsigned int sleep(unsigned int seconds); 用于让程序暂停执行指定的时间
参数:seconds指定程序暂停执行的秒数
返回值:成功则返回0;失败:若程序被信号中断,返回未休眠的秒数
(二)setbuf函数
所需头文件:#include <stdio.h>
原型:void setbuf(FILE *stream, char *buf); 设置指定文件流的缓冲区
参数:stream指向FILE对象的指针(需要设置缓冲区的文件流);buf 指向自定义缓冲区的指针。
全缓冲:如果 buf 指向一个大小大于0的缓冲区,那么IO操作将使用全缓冲模式;
无缓冲:如果buf为NULL,或者是大小为0,那么IO操作将变为无缓冲模式;
注意:
- 调用 setbuf 函数应该在打开文件流之后或者是任何IO操作之前,(建议在 fopen 函数之后使用 setbuf 函数,否则如果对 NULL 自定义缓冲区会出现问题)否则可能不会生效;
- 如果要使用自定义的缓冲区,确保缓冲区足够大,以避免缓冲区溢出;如果提供了缓冲区,其大小必须至少为 BUFSIZ 字节(通常在stdio.h中定义)。
- 当使用自定义缓冲区时,不要在buf指向的缓冲区被释放后再进行IO操作,以免未定义行为;
//文件设置 全缓存 (全缓存下换行符不会刷新缓存区)
char buf_size[BUFSIZ]={0};
setbuf(fp,buf_size);
fputs("hello world\n",fp);
printf("延时5s\n");
sleep(5);
fputs("hello world\n",fp);
fclose(fp);
(三)setvbuf函数
所需头文件:#include <stdio.h>
原型:int setvbuf(FILE *stream, char *buf, int mode, size_t size); 控制文件流的缓冲行为,允许指定缓冲模式和缓冲区的大小;该函数必须在对stream执行任何其他操作前调用(类setbuf)。
参数:
- stream 指向FILE对象的指针(需要设置缓冲区的文件流)。
- buf 指向自定义缓冲区的指针,如果为NULL,函数会自动分配一个大小为 size 的缓冲区。
- mode 缓冲模式,必须是以下之一:_IOFBF 全缓冲;_IOLBF 行缓冲;_IONBF 无缓冲
当mode为_IONBF时,size参数被忽略(因为无缓冲大小为0)。 - size 缓冲区的大小(以字节为单位)
返回值:成功则返回0;失败则返回非0值
//手动设置缓冲区
char buf[BUFSIZ]={0};
setvbuf(fp,buf,_IOLBF,sizeof(buf));//行缓存
//setvbuf(fp,buf,_IOFBF,sizeof(buf));//全缓存
fputs("hello world\n",fp);
printf("请查看文件中内容(已刷新缓冲区)\n");
sleep(3);
fputs("行缓冲设置成功\n",fp);
printf("请zaici查看文件中内容(已刷新缓冲区)\n");
sleep(3);
fclose(fp);
180




被折叠的 条评论
为什么被折叠?



