Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1426326
  • 博文数量: 842
  • 博客积分: 12411
  • 博客等级: 上将
  • 技术积分: 5772
  • 用 户 组: 普通用户
  • 注册时间: 2011-06-14 14:43
文章分类

全部博文(842)

文章存档

2013年(157)

2012年(685)

分类: 系统运维

2012-05-14 17:19:41



下面三个函数打开一个标准I/O流。



  1. #include <stdio.h>

  2. FILE *fopen(const char *restrict pathname, const char *restrict type);

  3. FILE *freopen(const char *restrict pathname, const char *restrict type, FILE *restrict fp);

  4. FILE *fdopen(int filedes, const char *type);

  5. 成功返回文件指针,错误返回NULL。


这三个函数的区别在于:


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来关闭。



  1. #include <stdio.h>

  2. int fclose(FILE *fp);

  3. 成功返回0,错误返回EOF。


任何缓冲的输出数据都在文件关闭前被冲洗。任何可能被缓冲的输入数据都会被舍弃。如果标准I/O库之前自动开辟了一个缓冲,这个缓冲会被释放。

当一个进程通过直接调用exit函数或从main函数返回而正常终止时,所有包含未写的缓冲数据的标准I/O流都会被冲洗,而且所有的标准I/O流都会关闭。


阅读(585) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~