打开流 fopen 、freopen和fdopen函数

打开流 fopen 、freopen和fdopen函数

转载 2015-12-21 14:13:07

fopen 、freopen和fdopen函数作用都是打开一个标准I/O流的,但是它们有一些略微的差别。从函数原型、函数描述、特殊用法。

一、函数原型

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

FILE *fdopen(int fd, const char *type);

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

返回值,若成功,返回文件指针,若失败,返回NULL

mode 参数类型

 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━

    字符              含义

────────────────────────────

    "r"           打开文字文件只读

    "w"           创建文字文件只写

    "a"           增补, 如果文件不存在则创建一个

    "r+"          打开一个文字文件读/写

    "w+"          创建一个文字文件读/写

    "a+"          打开或创建一个文件增补

    "b"           二进制文件(可以和上面每一项合用)

    "t"           文这文件(默认项)

━━━━━━━━━━━━━━━━━━━━━━━━━━━━

 文件使用方式        意 义

 “rt”      只读打开一个文本文件,只允许读数据

“wt”    只写打开或建立一个文本文件,只允许写数据

 “at”    追加打开一个文本文件,并在文件末尾写数据

 “rb”    只读打开一个二进制文件,只允许读数据

 “wb”    只写打开或建立一个二进制文件,只允许写数据

 “ab”     追加打开一个二进制文件,并在文件末尾写数据

 “rt+”    读写打开一个文本文件,允许读和写

 “wt+”   读写打开或建立一个文本文件,允许读写

 “at+”   读写打开一个文本文件,允许读,或在文件末追加数 据

 “rb+”    读写打开一个二进制文件,允许读和写

 “wb+”   读写打开或建立一个二进制文件,允许读和写

 “ab+”    读写打开一个二进制文件,允许读,或在文件末追加数据

二、函数描述

1、fopen函数:打开路径名为pathname的一个指定的文件

2、fdopen函数:打开已存在的文件描述符,使标准I/O流与该文件相结合。主要用于fopen不能打开的特殊文件(如管道和网路通信等),这时必须先调用设备专用函数以获得一个文件描述符,然后在用fdopen使一个标准I/O与该文件描述符相结合。

3、Freopen函数:在指定的流上打开一个指定的文件,如若该流已经打开,则先关闭该流。若该流已经定向,则使用freopen清除该定向。简单的说可以利用freopen函数重定向。此函数一般用于将一个指定的文件代开为一个预定义的流:stdout,stdin,stderr。可以利用freopen将标准流冲定向。不要在程序的一开始就使用freopen。因为标准输出流(标准输入流和标准错误输出流)是常量,是不可再分配文件描述符的。

三、特殊用法

1、fopen

在指定w或a类型创建一个新文件时,无法是么该文件的访问权限位,所以在mode参数​中不能有r类型。

2、fdopen

(1)在man手册中指出fdopen中的mode参数必须与fd原先的mode参数相匹配。这就是说这时的mode参数是原先mode参数的子集。否则会发生段错误。eg

#include

#include

#include

#include

//fdopen 中的mode的参数必须与参数fd的原先的读写权限相匹配

//参数mode 是fd原先读写权限的子集

int main(void)

{

    int fd = -1;

    int set = -1;   

    FILE *fp;

    //fd = open("./text", O_RDWR | O_APPEND);//no

    fd = open("./text", O_WRONLY | O_APPEND);//ok

    //fd = open("./text", O_RDONLY | O_APPEND);//no

    

    write(fd, "text", strlen("text"));

    printf("22222\n");

    fp = fdopen(fd, "w");

    set = ftell(fp);

    printf("11111\n");

    write(fileno(fp), "qwer", strlen("qwer"));

    printf("set = %d\n", set);

    exit(0);

}

​(2)在man手册中指出fdopen返回的文件指针的偏移量与参数文件描述符fd一致。eg:

#include

#include

#include

#include

#include

//fdopen 返回的fp的文件偏移量是 参数fd的偏移量。

int main(void)

{

    int fd = -1;

    int set = -1;   

    FILE *fp;

    fd = open("./text", O_RDONLY);

    lseek(fd, 0, SEEK_END);

    fp = fdopen(fd, "r");

    set = ftell(fp);

    ​printf("set = %d\n", set);

    exit(0);

}

(3)把原先error和end-of-file标志位清除,所以这时fdopen中的参数type为”w”或”w+”,不会造成截断文件长度。也就是说不会从文件开头写,会追加到现在偏移量之后。eg:

 #include

#include

#include

#include

#include

//因为在使用fdopen时,已经把error和end-of-file标志位清除了,所以"w"和"w+"不会截断文件,新写入的数据会追加原先文件的结尾。

int main(void)

{

    int fd = -1;

    int set = -1;   

    FILE *fp;

    fd = open("./text", O_WRONLY);

    lseek(fd, 0, SEEK_END);

    fp = fdopen(fd, "w");

    write(fileno(fp), "fdopen", strlen("fdopen"));

    set = ftell(fp);

    printf("set = %d\n", set);

    exit(0);

}

3、freopen重定向,如果这个流(参数fp指向的流)是打开的,则这个流将关闭。所以重新使用这个流时得重新打开。但这个流是标准输入/输出/错误输出流时,在调用freopen后重新打开将会比较麻烦。要借助于fgetpos/fsetpos和dup/dup2函数。下一遍详细介绍。

猜你喜欢

转载自blog.csdn.net/yu132563/article/details/83928277
今日推荐