本文主要介绍C语言中的标准I/O库,这是让我困惑过很久的一个知识点,我相信对于很多C语言的初学者,对I/O的概念其实并不是很清楚,今天想简要的介绍一下。本文参考《UNIX环境高级编程》。
先来看一个程序:
#include <stdio.h> int main(void) { printf("Hello,world!\n"); return 0; }
我觉得应该从文件I/O开始。
文件I/O,顾名思义,就是从文件读数据,并且将数据写到文件的这样一个接口。在UNIX系统中,经常使用的文件I/O函数有:open,read,write,lseek和close,其作用分别是打开文件,读文件,写文件,定位文件和关闭一个文件。那么如何获取一个指定的文件呢?这就需要利用文件描述符了。文件描述符是一个非负的整数,比如标准输入的文件描述符可能是0,标准输出的文件描述符可能是1,标准出错的是2,比如一个文件hello.c的文件描述符是5,等等。举个例子:
#include <fcntl.h> #include <unistd.h> #include <stdio.h> #define BUFFSIZE 4096 int main(void) { int n; char buf[BUFFSIZE]; while ((n = read(STDIN_FILENO,buf,BUFFSIZE)) > 0) if (write (STDOUT_FILENO,buf,n) != n) printf("write error\n"); if (n < 0) printf("read error\n"); exit(0); }该程序的作用是将标准输入的内容复制到标准输出上。
下面对该程序简单分析一下:头文件声明需要用到的函数,定义了一个大小4096的BUFFSIZE,STDIN_FILENO代表的是标准输入流的文件描述符,buf变量存放读入的内容,BUFFSIZE是大小,每次读取这么多的数据,只有当读入结束或者出错的时候才有可能不读入这么多的数据。这句话的意思就是从标准输入读入BUFFSIZE个数据,返回值为实际读入的数据个数。write函数将buf里的内容写到标准输出上,也就是STDOUT_FILENO,数量为n,也就是上次读取的内容。这就是程序的主体,当我们需要从其他文件读入或者写到其他文件(而不是标注输入输出)时,只需要将STDIN_FILENO和STDOUT_FILENO替换为我们指定的文件描述符就可以了,这个文件描述符可以通过open函数得到。
这个程序有个关键的地方,就是BUFFSIZE的大小,为什么是4096?
《UNIX环境高级编程》的作者测试过各种大小的情况:
我们看到,当BUFFSIZE为1时,花费的时间最长,因为内核需要对文件读写的次数最多,当BUFFSIZE变大时,读写次数变少,那么时间就短。这个BUFFSIZE的大小,就是缓冲区的大小,我们定义的buf[BUFFSIZE],就是缓冲区。它的目的就是,让内核读写文件数据的时候,是凑够了BUFFSIZE个数据一起读写,而不是一个一个字节单元去读或者写,这样能提高效率。
那么,标准I/O库是什么呢?标准I/O库就是给了一个适当的默认的缓冲区,而不用我们自己去设置。当然,自己是可以去修改的。流的概念也能理解了,一个流与一个特定的文件相关联,包括了文件描述符,缓冲区指针和缓冲区大小等信息。最终的I/O操作还是通过文件I/O来实现的(我猜),只是标准I/O已经给你设置一个默认的比较合适的缓冲区以提高读写效率。
原文地址:http://blog.csdn.net/bing_bing304/article/details/42641065