[ APUE ] 第五章 檔案和目錄
2.流和FILE物件
在前幾章的所有的IO函式中都是圍繞著“檔案描述符”進行的。而對於標準IO庫,它們的操作是圍繞著“流(stream)”進行的。用標準IO庫開啟或者建立一個檔案,就會使一個流與一個檔案相關聯。
流的定向(stream's orientation)決定了所讀寫的字元是單位元組還是多位元組的。流剛建立時是未定向的。在未定向的流上使用單位元組還是多位元組(wchar.h)的IO函式,會將流的定向設定為單位元組或多位元組。
只有兩個函式可以改變流的定向:freopen和fwide,分別用於清除流定向和設定流定向
#include <wchar.h> int fwide(FILE *stream, int mode);
返回值:正:寬定向 負:位元組定向 零:未定向。
mode為正:寬定向
mode為負:位元組定向
mode為0:不設定定向,返回該流定向的值
fwide並不改變已經定向的流的定向!
注意fwide返回值沒有涉及到出錯返回,那麼當流是無效的呢?我們可以在呼叫fwide之前清空errno,在返回後判斷errno的值。
當我們使用fopen開啟一個檔案時會返回一個FILE指標,這個指標指向一個結構體,包含了管理這個流的所有資訊。通常包括:實際IO用的檔案描述符(還是得用檔案描述符)、指向緩衝區的指標、緩衝區的長度、當前在緩衝區中的字元數以及出錯標誌等等。
3.標準輸入、標準輸出和標準錯誤
STDIN_FILENO , STDOUT_FILENO , STDERR_FILENO 三個檔案描述符,數字分別是0,1,2。
還有他們各自對應的FILE指標,stdin、stdout、stderr。這三個指標在<stdio.h>中
4.緩衝
標準庫提供緩衝是為了減少read和write的呼叫次數,從而提高效率。
-
全緩衝,當緩衝區填滿後才進行實際IO操作。對於駐留磁碟上的檔案通常使用全緩衝。緩衝區的獲取一般通過malloc獲得。
flush是標準IO緩衝區的寫操作。緩衝區可以由標準IO自動沖洗,也可呼叫fflush沖洗。
例如fflush可以將緩衝區內容寫到磁碟上。(還記得fflush(stdout)麼,可以將緩衝區內容衝到螢幕上。
-
行緩衝。在這種情況下遇到換行符標準IO庫就執行IO操作。抑或當緩衝區滿的時候也進行IO操作。
-
不帶緩衝。
stderr通常是不帶緩衝的,它會讓出錯資訊儘快輸出。
ISO C要求:
- 當且僅當標準輸入和標準輸出不指向互動式裝置室,他們才是全緩衝的。
- 標準錯誤絕不會是全緩衝的。
setbuf函式和setvbuf函式可以改變緩衝型別。
#include <stdio.h>
void setbuf(FILE *stream, char *buf);
int setvbuf(FILE *stream, char *buf, int mode, size_t size);
成功返回0,不成功返回非0
setbuf用於開啟或關閉緩衝機制。關閉緩衝buf為NULL,否則為緩衝區指標。
setvbuf可以指定緩衝型別,mode引數如下:
_IOFBF 全緩衝
_IOLBF 行緩衝
_IONBF 不帶緩衝
如果指定不帶緩衝就忽略buf和size(為0),如果buf是NULL,mode指定帶緩衝,則標準IO庫將自動分配緩衝區,大小為引數size。
如果buf是函式的區域性棧變數,則函式返回前必須關閉相關流!(一般沒人這麼幹吧。。
某些實現可能會在緩衝區裡存一些管理資訊,所以緩衝區實際可用大小小於size。
fflush引數為NULL可以沖洗所有輸出流。
5.開啟流
#include <stdio.h>
FILE *fopen(const char *pathname, const char *mode);
FILE *fdopen(int fd, const char *mode);
FILE *freopen(const char *pathname, const char *mode, FILE *stream);
freopen在指定流上開啟指定檔案,若流已經開啟則先關閉該流(UNIX下開啟檔案會自動分配到數值最小的空閒描述符上——《unix程式設計實踐教程》),若已經定向則清除定向(害記得第一次爆零開火車