标准I/O库之流、FILE对象、三个标准流以及缓冲

对于标准I/O库而言,它们所有的操作均是围绕着流来进行的。标准I/O文件流可用于单字节或多字节字符集。流的定向决定了所读、写的字符是单字节还是多字节。只有两个函数可改变流的定向,freopen函数清除一个流的定向;fwide函数可用于设置流的定向。

#include <stdio.h>
#include <wchar.h>
int fwide(FILE *fp, int mode);
函数返回值:若流是宽定向,返回正值;若流是字节定向的,返回负值;若流是未定向的,返回 0。

根据mode参数的不同值,fwide函数执行不同的工作。

  • mode参数值为负,fwide函数将试图使指定的流是字节定向的。
  • mode参数值为正,fwide函数将试图使指定的流为宽定向的。
  • mode参数值为0,fwide函数将不设置流的定向,但返回标识该流定向的值。

对于一个进程而言预定义了3个流,并且这3个流可以自动地被进程使用,它们分别是标准输入、标准输出以及标准错误。这些流引用的文件与文件描述STDIN_FILENOSTDOUT_FILENOSTDERR_FILENO所引用的相同。这三个标准I/O流通过预定义文件指针stdinstdoutstderr加以引用。

标准I/O库提供缓冲的目的是尽可能减少使用readwrite调用的次数。

标准I/O提供以下三种类型的缓冲

  • 全缓冲。这种情况下,在填满标准I/O缓冲区后才进行实际I/O操作。对于驻留在磁盘上的文件通常是有标准I/O库实施全缓冲的。在一个流上执行第一次I/O操作时,相关标准I/O通常调用malloc获得需使用的缓冲区。冲洗(flush)在标准I/O库方面,flush(冲洗)意味着将缓冲区中的内容写到磁盘上。在终端驱动程序方面,flush(刷清)表示丢弃了已存储在缓冲区中的数据。
  • 行缓冲。在这种情况下,当在输入和输出中遇到换行符时(\n),标准I/O库执行I/O操作。这允许我们一次输出一个字符,但只有在写了一行之后才进行实际I/O操作。当流涉及一个终端时,通常使用行缓冲。
  • 不带缓冲。标准I/O库不对字符进行缓冲存储。标准错误流stderr通常是不带缓冲的,因为需要使得出错信息尽快的显示出来,而不管它们是否含有一个换行符。

注意行缓冲有两个限制,第一,因为标准I/O库用来收集每一行缓冲区的长度是固定的,所以只要填满了缓冲区,那么即使还没有写一个换行符也进行I/O操作。第二,任何时候只要通过标准I/O库要求从(a)一个不带缓冲的流,或者(b)一个行缓冲的流得到输入数据,那么就会冲洗所有行缓冲输出流。

ISO C要求下列缓冲特征:

  • 当且仅当标准输入和输出并不指向交互式设备时,它们才是全缓冲的。
  • 标准错误绝不会是全缓冲的。
  • 标准错误是不带缓冲的。
  • 若是指向终端设备的流,则是行缓冲的;否则是全缓冲的。

对于不想使用系统默认缓冲的情形时,可以通过以下两个函数进行更改缓冲类型。

#include <stdio.h>
void setbuf(FILE *restrict fp, char *restrict buf);
int setvbuf(FILE *restrict fp, char *restrict buf, int mode, size_t size);
函数返回值:若成功,返回 0;若出错,返回非0。

上面函数的各个选项总结如下:

函数 mode buf 缓冲区及长度 缓冲类型
setbuf —— 非空 长度为BUFSIZE的用户缓冲区buf 全缓冲或行缓冲
  —— NULL 无缓冲区 不带缓冲
setvbuf _IOFBF 非空 长度为size的用户缓冲区buf 全缓冲
    NULL 合适长度的系统缓冲区buf 全缓冲
  _IOLBF 非空 长度为size的用户缓冲区buf 行缓冲
    NULL 合适长度的系统缓冲区buf 行缓冲
  _IONBF 忽略 无缓冲区 不带缓冲

任何时候,我们均可强制冲洗一个流。

#include <stdio.h>
int fflush(FILE *fp);
返回值:若成功,返回0;若出错,返回EOF。

此函数使该流所有的未写的数据都送到内核。作为一种特殊情形,若fpNULL,则此函数将导致所有输出流被冲洗。

发布了229 篇原创文章 · 获赞 17 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qq_40073459/article/details/104401050