1. 程式人生 > 實用技巧 >[ APUE ] 第五章 檔案和目錄

[ 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的呼叫次數,從而提高效率。

  1. 全緩衝,當緩衝區填滿後才進行實際IO操作。對於駐留磁碟上的檔案通常使用全緩衝。緩衝區的獲取一般通過malloc獲得。

    flush是標準IO緩衝區的寫操作。緩衝區可以由標準IO自動沖洗,也可呼叫fflush沖洗。

    例如fflush可以將緩衝區內容寫到磁碟上。(還記得fflush(stdout)麼,可以將緩衝區內容衝到螢幕上。

  2. 行緩衝。在這種情況下遇到換行符標準IO庫就執行IO操作。抑或當緩衝區滿的時候也進行IO操作。

  3. 不帶緩衝。

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程式設計實踐教程》),若已經定向則清除定向(害記得第一次爆零開火車