缓冲的几个基本概念
缓冲的作用:减少系统read和write的次数。
全缓冲
系统标准I/O缓冲区被写满时才进行真正的I/O操作。
磁盘文件一般使用全缓冲
全缓冲使用malloc来分配缓冲区
行缓冲
系统遇到换行符时进行真正的I/O操作。
Terminal一般使用行缓冲
行缓冲有固定的size,当这个固定size的行缓冲区被填满时,不管有没有遇到换行符都开始进行一次I/O操作。
行缓冲在得到输入数据时,会自动刷新输出流。这里说的得到数据,指的时数据在输入流中, 并不要求输入的数据一定被内核读取了。
不带缓冲的流
没有缓冲区,直接写入文件。
标准错误流默认使用不带缓冲。
刷新flush
在使用全缓冲或者行缓冲时,即使我们的缓冲区未被写满(全缓冲)、或者还没遇到换行符(行缓冲),(也就是还没达到进行真正I/O的默认条件),只要我们使用flush,那么就会立即执行I/O操作,将数据流填入内核。
#include <stdio.h>
int fflush(FILE *fp);
ISO C的要求
标准输入、输出流:当且仅当I/O操作不涉及交互式设备的时候,使用全缓冲
标准错误:永远不适用全缓冲(ps:应该是考虑遇到特殊故障,如果使用全缓冲可能无法记录错误,比如突然断电,可能缓冲区内
数据就无法进行记录。)
一般情况(Most implementation):
标准错误:使用不带缓冲区的流
其它流:涉及到Terminal时使用行缓冲,其它情况使用全缓冲
改变数据流缓冲类型
setbuf和setvbuf可以用来改变数据流的缓冲类型
#include <stdio.h> void setbuf(FILE *restrict fp,char *restrict buf); int setvbuf(FILE *restrict fp,char *restrictbuf,intmode,size_tsize); Returns: 0 if OK, nonzero on error
intmode 可以取以下值:
_IOFBF fully buffered _IOLBF line buffered _IONBF unbuffered
setbuf和setvbuf的具体功能如Figure5.1所示:
对于setbuf来说,如果buf参数为空,则关闭数据流的缓冲功能;如果buf的值不为空,指向一个缓冲区,那么就将缓冲类型设置为全缓冲(一些系统实现了当数据流来自Terminal时,设置为行缓冲)
对于setvbuf的_IPFBF和_IOLBF,如果buf为空,则为系统默认缓冲区,如果buf不为空,则使用用户自定义的缓冲区。
流
当一个文件被打开时,可以获得文件描述符。通过文件描述符可以对文件进行I/O操作。而I/O操作是通过流完成的。
流的定向:
在Unix系统中,使用 ASCII标准时,一个字符可能用一个字节表示,这是流导向为字节导向;使用国际标准时,一个字节可能用两个字节表示,这是流定向为宽字符定向。
fwide
#include <stdio.h> #include <wchar.h> int fwide(FILE *fp,intmode);
功能:
设置流定向
参数:
fp:打开的文件描述符
intmode:带符号的int值,
正数:表示宽字符定向
负数:表示字节定向
0:
表示不进行定向设置
返回值:
流的定向,与intmode类似。
文件对象File object
使用fopen打开文件时,会创建一个指向FILE型的的文件对象的指针。
FILE对象几乎包括所有对文件的I/O操作所需要的信息。