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