1. 程式人生 > >開啟流 fopen 、freopen和fdopen函式

開啟流 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函式。下一遍詳細介紹。