全部博文(842)
分类: 系统运维
2012-05-14 17:19:41
下面三个函数打开一个标准I/O流。
这三个函数的区别在于:
1、fopen函数打开一个指定的文件。
2、freopen函数在一个指定的流上打开一个指定的文件,并关闭之前打开的流。如果之前的流有方向,freopen会清除它。这个函数被典型用来打开一个指定的文件,作为其中一个预定义的流:标准输入、标准输出或标准错误。
3、fdopen函数接受一个已有的文件描述符,它可以通过open、dup、dup2、fcntl、pipe、socket、socketpair或
accept函数得到。这个文件描述符会和标准I/O流关联起来。这个函数经常和创建管道和网络通信渠道的函数的返回值一起使用。因为这些特殊类型的文件
不能用标准I/O函数fopen打开,所以我们必须调用设备相关的函数来得到一个文件描述符,再通过fdopen函数把这个描述符与标准I/O流相联起
来。
fopen和freopen两个都是ISO C的一部分。fdopen是POSIX.1的一部分,因为ISO C没有处理文件描述符。
下表显示了ISO C为type参数指定的15个值:
打开一个标准I/O流的type参数 |
|
type | 描述 |
r或rb | 打开来读 |
w或wb | 打开来写 |
a或ab | 添加;打开写入文件末尾,或创建来写 |
r+或r+b或rb+ | 打开来读写 |
w+或w+b或wb+ | 裁切成0长度或创建来读写 |
a+或a+b或ab+ | 打开或创建来在文件尾读写 |
使用字符b作为类型的一部分允许标准I/O系统来区分一个文本文件和二进制文件。因为UN不X内核不区分这两种文件类型,指定这个字符b没有效果。
在fdopen里,type参数的含义有一些小区别。因为描述符已经被打开了,所以打开来写不会裁切这个文件。(例如,如果描述符由open函数创建,而 且这个文件已经存在,那么O_TRUNC标志会控制这个文件是否被裁切。fdopen函数不能简单的裁切任何它打开来写的文件。)还有,标准I/O添加模 式不能创建这个文件(因为由一个描述符指向的这个文件必须存在)。
当一个文件用添加类型打开时,每次写都会发生在文件的当前末尾。如果多个进程使用标准I/O添加模式打开同一个文件,每个进程的数据都会被正确写入到这个文件。
在4.4BSD之前的Bdrkeley的fopen的各种版本,以及在Kernighan and Ritchie[1988]第177页上展示的简单版本,没有正确地处理添加模式。这些版本在流打开时用lseek到文件末尾。为了当多进程被引入时正确 支持添加模式,文件必须用O_APPEND标志打开,我们已经在3.3节讨论过了。每次写前调用lseek也不能工作,正如我们在3.11节讨论的。
当一个文件打开来读写(类型中的+号)时,会有以下限制:
1、输出后,没有fflush、fseek、fsetpos或rewind的操作的话,不能直接进行输入。
2、输入后,没有fseek、fsetpos、rewind或一个碰到文件尾的读操作的话,不能直接进行输出。
下表总结了打开一个流的6种方式:
打开一个标准I/O流的6种方式 |
||||||
限制 | r | w | a | r+ | w+ | a+ |
文件必须存在 | * | * | ||||
文件之前的内容被丢弃 | * | * | ||||
流可以读 | * | * | * | * | ||
流可以写 | * | * | * | * | * | |
流只能在末尾写 | * | * |
注意如果一个新文件通过指定一个w或a的类型创建,我们不能指定这个文件的访问权限位,因为我们本可以在open函数或creat函数来做这件事(第3章)。
默认情况下,流以完全缓冲方式打开,除非它指向一个终端设备,在这种情况下它是行缓冲的。一旦流被打开,在我们对其做任何操作之前,如果愿意的话,我们可以改变这个缓冲,通过使用上节提到的setbuf和setvbuf函数。
一个打开的流可以调用fclose来关闭。
任何缓冲的输出数据都在文件关闭前被冲洗。任何可能被缓冲的输入数据都会被舍弃。如果标准I/O库之前自动开辟了一个缓冲,这个缓冲会被释放。
当一个进程通过直接调用exit函数或从main函数返回而正常终止时,所有包含未写的缓冲数据的标准I/O流都会被冲洗,而且所有的标准I/O流都会关闭。