通常使用标准I/O的第一步就是使用fopen()打开一个文件(回忆一下,stdin、stdout、stderr文件却是自动打开的)。fopen()函数不仅 打开一个文件,而且 建立了一个缓区(在读写模式下将建立两个缓冲区),还创建了一个包含文件和缓冲区相关数据的数据结构。不仅如此,fopen()还 返回指向该结构的指针 ,供其他函数知道如何找到该结构。假设把这个值赋给了一个名叫fp的指针变量。我们称fopen()函数打开了一个流。如果文件以文本模式打开,可以得到一个文本流;如果以二进制模式打开,那么就得到一个二进制流。
这个数据结构通常包括一个 文件位置指示器,以确定在流中的当前位置。它还包括错误指示器和文件结尾指示器、一个指向缓冲区起始处的指针、一个文件标识符,和一个记录实际复制到缓冲区中的字节数的计数器。
我们着重考虑文件输入。通常,下一步就是调用stdio.h头文件中声明的某个输入函数,比如scanf()、getc(),或fgets()。调用这些函数中的任意一个,都 会的 把一块数据从文件复制到缓冲区中。缓冲区的大小依赖于具体实现 ,但通常是512字节或者它的倍数。除了填充缓冲区以外,初次函数调用还将设置fp所指的结构中的值。特别地,将设置流的当前位置和复制到缓冲区中的字节数。通常当前位置从字节0开始。
数据结构和缓冲区初始化以后,输入函数将从缓冲区中读取所请求的数据。同时,文件位置指示器被置为紧随最后一个被读取字符的位置。因为stdio.h定义的所有输入函数都使用同一个缓冲区,所以任何一个被调函数都将在前一个任何函数调用停止的地方继续开始。
当输入函数检测 到已经读取了缓冲区中的全部字符时,它会请求系统将下一个缓冲区大小的数据复制到缓冲区。通过这种方式,输入函数可以读入函数中的全部内容,直到文件结尾。函数在读入最后 一缓冲区数据中的最后一个字符 后,会将文件结尾指示器的值设置为真。于是下一个被调用函数将返回EOF。
以类似的方式,输出函数将数据写入到缓冲区。当缓冲区已满时,就将数据复制到文件中。