apue标准IO库那些事儿,都有哪些细节和用法?
摘要:提起标准 IO 库,第一印象就是 printfscanf,这有什么可说的?但是一个流是如何处理宽窄字符集、缓存方式的?如何在程序内部将标准输出重定向到文件?FILE* 与 fd 是如何相互转换的?在处理大文件时 fseekfseeko
前言
标准 IO 库自 1975 年诞生以来,至今接近 50 年了,令人惊讶的是,这期间只对它做了非常小的修改。除了耳熟能详的 printf/scanf,回过头来对它做个全方位的审视,看看到底优秀在哪里。
打开关闭
要想使用 IO 流就必需打开它们。三个例外是标准输入 stdin、标准输出 stdout、标准错误 stderr,它们在进入 main 时就准备好了,可以直接使用,与之对应的文件描述符分别是 STDIN_FILENO / STDOUT_FILENO / STDERR_FILENO。除此之外的流需要打开才能使用:
FILE* fopen(const char * restrict path, const char * restrict mode);
FILE* fdopen(int fildes, const char *mode);
FILE* freopen(const char *path, const char *mode, FILE *stream);
FILE* fmemopen(void *restrict *buf, size_t size, const char * restrict mode);
fopen 用于打开指定的文件作为流
fdopen 用于打开已有的文件描述符作为流
freopen 用于在指定的流上打开指定的文件
fmemopen 用于打开已有的内存作为流
大部分打开操作都需要提供 mode 参数,它主要由 r/w/a/b/+ 字符组成,相关的组合与 open 的 oflag 参数对应关系如下:
mode
oflag
r
O_RDONLY
r+
O_RDWR
w
O_WRONLY | O_CREAT | O_TRUNC
w+
O_RDWR | O_CREAT | O_TRUNC
a
O_WRONLY | O_CREAT | O_APPEND
a+
O_RDWR | O_CREAT | O_APPEND
其中 b 表示按二进制数据处理,不提供时按文本数据处理,不过 unix like 的文件不区分二进制数据与文本数据,加不加没什么区别,所以上面没有列出。
fdopen 提供了一种便利,将已有的 fd 封装在 FILE* 中,特别当描述符是通过接口传递进来时就尤为有用了。
