标准IO库学习
第一次接触标准IO库,就是经典的Hello world。实际上标准IO库里面还是很多细节我一直都不知道。《UNIX环境高级编程》专门有一章讲述标准IO库。标准IO库的函数在头文件stdio.h中声明。标准IO库不仅仅针对UNIX实现,所以它是由ISO C 标准说明。处理缓冲区分配、优化长度执行IO等。使用标准库让用户不用担心如何选取正确的正确选择块长度。
IO缓冲区
为什么要提供缓冲区呢?用户程序读写文件,需要通过操作系统的内核来执行,然后由内核驱动磁盘完成读写操作,也就是通过系统调用read和write来完成。系统调用是耗时的操作,要尽量少地调用。通过缓冲区可以减少系统调用read和write的次数。
标准IO库提供了下面3中类型的缓冲:
- 全缓冲:填满标准IO缓冲区才进行实际的IO操作
- 行缓冲:输入和输出中遇到换行符的时候,标准IO库进行实际IO操作。当然,标准IO缓冲区填满的时候也要进行实际IO操作。
- 不带缓冲:用户程序每次调用标准IO库都通过操作系统内核进行实际IO操作。
下面这个程序可以证明标准输出是行缓冲
#include <stdio.h> int main() { printf("hello world"); while(1); return 0; }
这个程序在并不会打印出“hello world" ,因为没有写上换行符而缓冲未满。
如何设置缓冲类型?
setbuf()
setvbuf()
流和FILE对象
对操作系统内核而言,所有打开的文件都是通过文件描述符来引用。当打开一个文件时,即返回一个文件描述符。而对于标准IO库中,他们的操作对象是流。当打开一个文件时,即使用一个流与一个文件相关联。打开一个流时,通常返回一个指向FILE结构体的指针。它包含了标准IO库为管理流所需要的所有信息,包括实际的IO文件描述符。stdin,stdout,stderr 就是三个预定义的文件指针。
打开流
- fopen 打开指定的文件
- freopen 在指定的流上打开一个指定的文件
- fdopen 获取一个现有的文件描述符,并使一个标准的IO流和该文件描述符结合。
读写流
每次一个字符 |
getc fgetc getchar
putc fputc putchar |
|
每次一行 |
fgets gets(不推荐使用)
fputs puts |
|
直接IO(二进制IO),一次读或写整个结构 |
fread fwrite |
|