浅析标准I/O库

 本文主要介绍C语言中的标准I/O库,这是让我困惑过很久的一个知识点,我相信对于很多C语言的初学者,对I/O的概念其实并不是很清楚,今天想简要的介绍一下。本文参考《UNIX环境高级编程》。

        先来看一个程序:

#include <stdio.h>

int main(void)
{
    printf("Hello,world!\n");
    return 0;
}

        这可能是所有学习C语言的人写的第一个程序,这个程序主要用到的就是I/O,其中,头文件是标准 I/O库文件,printf函数的作用是将引号内的字符输出到标准输出流上,一般是指程序的控制终端,或者说,显示在屏幕上。那么,如果要输出到某一个文件上,可以用fprintf,该函数可以将字符写至指定的流。那么,流是什么概念?通常,流是一个名为FILE的结构体,它包含了标准I/O库为管理该流所需要的所有信息,包括:用于实际I/O的文件描述符,指向用于该流缓冲区的指针,缓冲区的长度等等。问题来了,文件描述符是什么?缓冲区又是什么概念?这个流到底是什么东西?


        我觉得应该从文件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已经给你设置一个默认的比较合适的缓冲区以提高读写效率。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值