标准I/O库之打开和关闭流

时间:2023-03-10 07:27:02
标准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。

标准I/O库之打开和关闭流

使用字符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/