之前所介绍的I/O函数如open、read、write、lseek以及close,均是针对文件描述符的,即一个整数,而下面介绍的标准I/O函数,均是针对流进行操作的,即一个FILE类型指针(FILE对象是一个结构,包含对应文件若干信息)
标准输入、标准输出以及标准错误输出的文件描述符和流对应关系为:
- 标准输入:STDIN_FILENO/stdin
- 标准输出:STDOUT_FILENO/stdout
- 标准错误输出:STDERR_FILENO/stderr
标准I/O自动进行缓存管理,尽可能减少使用read和write调用的数量,提高效率
FILE * fopen(const char * pathname, const char * type);
返回一个流,即FILE指针
参数type表示流的读写权限,有以下选项:
- r:只读,文件必须存在
- r+:读写,文件必须存在
- w:只写,若文件不存在则新建,若存在则长度清0
- w+:读写,若文件不存在则新建,若存在则长度清0
- a:只写,若文件不存在则新建,若存在则在文件尾部追加内容
- a+:读写,若文件不存在则新建,若存在则在文件尾部追加内容
后缀b表示打开的是二进制文件,而非文本文件。该选项只用于增强代码可读性,对编译器并无影响
除非流引用终端设备,否则系统默认为全缓存(即当填满I/O缓存后才进行实际I/O操作)
int fclose(FILE * fp);
关闭一个打开的流,在关闭前刷新缓存中的输出数据,丢弃缓存中的输入数据,释放缓存
进程正常终止时,刷新所有缓存,关闭所有I/O标准流
标准I/O的流读写可分为以下三种:
- 每次一个字符的I/O:fgetc、fputc(getchar相当于fgetc(stdin),putchar相当于fputc(stdout))
- 每次一行的I/O:fgets、fputs
- 直接I/O:fread、fwrite
前两者适用于文本数据的I/O,最后一个适合于二进制数据的I/O
int fgetc(FILE * fp);
int fputc(int c, FILE * fp);
返回值为下一个字符
char * fgets(char * buf, int n, FILE * fp); //fgets若成功则返回buf指针,失败则返回NULL
int fputs(const char * buf, FILE * fp); //fpust若成功则返回非负值,失败则返回EOF
对fgets,指定缓存的长度n。此函数一直读到下一个新行符为止,但是不超过n-1个字符。
对于二进制I/O,使用fgetc、fgets之类的针对字符的I/O函数会出现很多问题,这里应使用fread、fwrite
size_t fread(void * buf, size_t size, size_t nobj, FILE * fp); //返回读取元素数
size_t fwrite(const void * buf, size_t size, size_t nobj, FILE * fp); //返回写入元素数
size为单个元素的大小(字节数),nobj为元素个数
int fprintf(FILE * fp, const char * format, ……); //成功返回输出字符数,出错返回负值
int fscanf(FILE * fp, const char * format, ……);
fprintf相对于printf来说,可以指定流
int fileno(FILE * fp);
获得指定流对应的文件描述符