1、引言ide
标准I/O库不只是UNIX,许多i其余操做系统都实现了标准I/O库,因此这个库由ISO C标准说明。标准I/O库处理不少细节,如缓冲区分配,以及优化的块长度执行I/O等。这使得它便于用户使用,可是若是咱们不能深刻了解I/O库函数的操做,也会带来一些问题。函数
2、流和FILE对象优化
第三章中全部I/O函数都是围绕文件描述符的。当打开一个文件是,即返回一个文件描述符,而后该文件描述符就用于后续的I/O操做。而对于标准I/O库,它们的操做是围绕流(stream)进行的,当用标准I/O库打开或建立一个文件时,咱们已使一个流与一个文件相关联。标准I/O文件刘可用于单字节或款字节字符集。流的定向(stream‘s orientation)决定了所读、写的字符是单字节仍是多字节的。只有两个函数可改变流的定向。freopen函数清除一个流的定向,fwide函数可用于设置流的定向。ui
#include <stdio.h> #include <wchar.h> int fuidw(FILE *fp, int mode); //若流是款定向的,返回正值,若流是字节定向的,返回负值;若流是未定向的,返回0
mode参数为正值,fwide将试图使指定的流是宽定向的;mode参数为负值,将试图使指定的流是字节定向的;当mode为0,不作定向,返回标识流的定向值。须要注意两点:fwide并不改变已定向流的定向;fwide无出错返回。spa
3、标注输入、标准输出和标准错误操作系统
对一个进程预约义了3个流,他们能够自动地被进程使用,他们是:标注输入、标注输出和标准错误。这些流与第三章提到的文件描述符STDIN_FILENO、STDOUT_FILENO和STDERR_FILENO所引用相同。这三个标准I/O流经过预约义文件指针stdin、stdout和stderr加以引用。这三个文件指针定义在头文件<stdio.h>中。指针
4、缓冲rest
标准I/O库提供缓冲的目的是进了能减小使用read和write调用的次数。他也对每一个I/O流自动地进行缓冲管理。标准I/O库提供三种类型的缓冲:code
一、全缓冲:这种状况下,在填满标准I/O缓冲区才进行实际I/O操做;对于驻留在磁盘上的文件一般是由标准I/O库事实全缓冲的。对象
二、行缓冲:在这种状况下,当在输入和输出中遇到换行符时,标准I/O库执行I/O操做;当流涉及到终端时,一般使用行缓冲。对于行缓冲有两个限制。第一,由于标准I/O库用来收集每一行的缓冲区的长度是固定的,因此只要填满了缓冲区,那么即便尚未写一个换行符,也进行I/O操做;第二,任什么时候候只要经过标准I/O库从(a)一个不带缓冲的流,或者(b)一个航缓冲的流(它从内核请求须要数据,其请求的数据可能已在缓冲区)获得输入数据,那么就会冲洗全部行缓冲输出流。
三、不带缓冲:标准I/O库不对字符进行缓冲;标准错误流stderr一般是不带缓冲的,这就是的出错信息能够尽快显示出来,而无论他们是否含有一个换行符。
ISO C要求下列缓冲特征:当且仅当标准输入和标准输出并不指向交互式设备时,他们才是全缓冲的;标准错误决不会是全缓冲的。大多数系统默认的是:标准错误是不带缓冲的;指向终端设备的流,则是行缓冲的,不然是全缓冲的。
对于任何一个给定的流,若是咱们并不喜欢这些系统默认,则可调用下列两个函数中的一个更改缓冲类型:
#include <stdio.h> void setbuf(FILE *restrict fp, char *restrict buf); void setvbuf(FILE *restrict fp, cahr *restrict buf, int mode, size_t size);
setbuf函数能够打开或关闭缓冲机制。为了带缓冲进行I/O,参数buf必须指向一个长度为BUFSIZ的缓冲区,一般在此以后该流就是全缓冲的,可是若是该流与一个终端设备相关,那么某些系统也可将其设置为行缓冲的;为了关闭缓冲,将buf设置为NULL。
setvbuf函数能够精确地说明所需的缓冲类型。这些用mode参数实现:_IOFBF、_IOLBF、_IONBF,若是指定一个不带缓冲的流,则忽略buf和size参数;若是指定全缓冲或行缓冲,则buf和size可选择地指定一个缓冲区及长度。若是该流是带缓冲的,而buf是NULL,则标准I/O库将自动地为该流分配适当长度的缓冲区。若是在一个函数内分配一个自动变量类的标准I/O缓冲区。则从该函数返回以前,必须关闭该流。通常状况都应由系统选择缓冲区的长度并自动分配缓冲区,在这种状况下,标准I/O库自动释放缓冲区。
术语冲洗(flush)说明标准I/O缓冲区的写操做。缓冲区可由标准I/O例程自动地冲洗,或者能够调用函数fflush冲洗一个流。flush有两层意思:在标准I/O库方面,flush意味着将缓冲区中的内容写到磁盘上;在终端驱动程序方面,flush标识丢弃已存储在缓冲区的数据。
#include <stdio.h>
int fflush(FILE *fp);
次函数是该流全部威胁的数据都被传送至内核。做为一种特殊情形,如若fp是NULL,则次函数将致使全部输出流被冲洗。
5、打开流
#incldue <stdio.h> FILE *fopen(const char *restrict pathname, const char *restrict type); FILE *freopen(const char *restrict pathname. const char *restrict type, FILE *restrict fp); FILE *fdopen(int fd, const char *type);
上面三个函数均可以打开一个标准的I/O流,区别是:fopen打开一个流;freopen在一个指定的流上打开一个指定的文件,如若该流已经打开,则先关闭该流。如该流已经定向,则使用freopen清除该定向。次函数通常用于将一个指定的文件打开为一个预约义的流:标准输入、标准输出和标准错误;fdopen函数娶一个已有的文件描述符,并使一个标准的I/O流与该描述符相结合。
type参数指定对该I/O流的读、写方式,ISO C规定参数能够有15中不一样的值(r/w/a/r+/w+/a+)。须要注意的是标准I/O库是能够区分文本文件和二进制文件,由于UNIX内核并不对这两种文件进行区分,因此在UNIX系统环境下指定字符b做为type的一部分实际上并没有做用。
当以读和写类型打开一个文件时,具备以下限制:若是中间没有fflush、fseek、fsetops或rewind,则在输出的后面不能直接跟随写入;若是中间没有fseek、fsetops或rewind,或者一个输入操做没有达到文件尾端,则在输入操做以后不能跟随输出。
除非流引用终端设备,不然按系统默认,该流被打开时是全缓冲的。若流引用终端设备,则该流是行缓冲的。一旦打开了流,那么在对该流执行任何操做以前,若是但愿,则可以使用setbuf和servbuf改变缓冲的类型。
#include <stdio.h>
int fclose(FILE *fp);
在该文件被关闭以前,冲洗缓冲中的输出数据,缓冲区中的任何输入数据被丢弃,若是标准I/O库已经为该流自动分配了一个缓冲区,则释放该缓冲区。当一个进程正常终止时,则全部带威胁缓冲数据的标准I/O流都被冲洗,全部打开的标准I/O流都被关闭。