标准I/O库之打开和关闭流
下列三个函数打开一个标准I/O流。
#include <stdio.h> FILE *fopen( const char *restrict pathname, const char *restrict type ); FILE *freopen( const char *restrict pathname, const char *restrict type, FILE *restrict fp ); FILE *fdopen( int filedes, const char *type ); 三个函数的返回值:若成功则返回文件指针,若出错则返回NULL
这三个函数的区别是:
(1)fopen打开一个指定的文件。
(2)freopen在一个指定的流上打开一个指定的文件,如若该流已经打开,则先关闭该流。若该流已经定向,则freopen清除该定向。此函数一般用于将一个指定的文件打开为一个预定义的流:标准输入、标准输出或标准出错。
(3)fdopen获取一个现有的文件描述符(我们可能从open、dup、dup2、fcntl、pipe、socket、socketpair或accept函数得到此文件描述符),并使一个标准的I/O流与该描述符相结合。此函数常用于由创建管道和网络通信通道函数返回的描述符。因为这些特殊类型的文件不能用标准I/O fopen函数打开,所以我们必须先调用设备专用函数以获得一个文件描述符,然后用fdopen使一个标准I/O流与该描述符相关联。
type参数指定对该I/O流的读、写方式,ISO C规定type参数可以有15种不同的值,见表5-2。
使用字符b作为type的一部分,这使得标准I/O系统可以区分文本文件和二进制文件。因为UNIX内核并不对这两种文件进行区分,所以在UNIX系统环境下指定字符b作为type的一部分实际上并无作用。
对于fdopen,type参数的意义稍有区别。因为该描述符已被打开,所以fdopen为写而打开并不截短该文件。另外,标准I/O添写方式也不能用于创建该文件(因为如若一个描述符引用一个文件,则该文件一定已经存在)。
当用添写方式打开一文件后,则每次写都将数据写到文件的当前尾端处。如若有多个进程用标准I/O添写方式打开了同一文件,那么来自每个进程的数据都将正确地写到文件中。
当以读和写类型打开一文件时(type中+符号),具有下列限制:
如果中间没有fflush、fseek、fsetpos或rewind,则在输出的后面不能直接跟随输入。
如果中间没有fseek、fsetpos或rewind,或者一个输入操作没有到达文件尾端,则在输入操作之后不能直接跟随输出。
对应于表5-2,我们在表5-3中列出了打开一个流的6种不同的方式。
表5-3 打开一个标准I/O流的6种不同的方式
限制 |
r |
w |
a |
r+ |
w+ |
a+ |
文件必须已存在 | @ | @ | ||||
擦除文件以前的内容 | @ | @ | ||||
流可以读 | @ | @ | @ | @ | ||
流可以写 | @ | @ | @ | @ | @ | |
流只可在尾端写 | @ | @ |
注意,在指定w或a类型创建一个新文件时,我们无法说明该文件的访问权限位。
除非流引用终端设备,否则按系统默认的情况,流被打开时是全缓冲的。若流引用终端设备,则该流是行缓冲的。一旦打开了流,那么在对该流执行任何操作之前,如果希望,则可使用setbuf和setvbuf改变缓冲的类型。
调用fclose关闭一个打开的流。
#include <stdio.h> int fclose( FILE *fp ); 返回值:若成功则返回0,若出错则返回EOF
在该文件被关闭之前,冲洗缓冲区中的输出数据。丢弃缓冲区中的任何输入数据。如果标准I/O库已经为该流自动分配了一个缓冲区,则释放此缓冲区。
当一个进程正常终止时(直接调用exit函数,或从main函数返回),则所有带未写缓冲数据的标准I/O都会被冲洗,所有打开的标准I/O流都会被关闭。
本篇博文内容摘自《UNIX环境高级编程》(第二版),仅作个人学习记录所用。关于本书可参考:http://www.apuebook.com/。