APUE(5)---標準I/O庫 (1)

1、引言ide

  標準I/O庫不只是UNIX,許多i其餘操做系統都實現了標準I/O庫,因此這個庫由ISO C標準說明。標準I/O庫處理不少細節,如緩衝區分配,以及優化的塊長度執行I/O等。這使得它便於用戶使用,可是若是咱們不能深刻了解I/O庫函數的操做,也會帶來一些問題。函數

2、流和FILE對象優化

  第三章中全部I/O函數都是圍繞文件描述符的。當打開一個文件是,即返回一個文件描述符,而後該文件描述符就用於後續的I/O操做。而對於標準I/O庫,它們的操做是圍繞流(stream)進行的,當用標準I/O庫打開或建立一個文件時,咱們已使一個流與一個文件相關聯。標準I/O文件劉可用於單字節或款字節字符集。流的定向(stream‘s orientation)決定了所讀、寫的字符是單字節仍是多字節的。只有兩個函數可改變流的定向。freopen函數清除一個流的定向,fwide函數可用於設置流的定向。ui

#include <stdio.h>
#include <wchar.h>
int fuidw(FILE *fp, int mode);
//若流是款定向的,返回正值,若流是字節定向的,返回負值;若流是未定向的,返回0

  mode參數爲正值,fwide將試圖使指定的流是寬定向的;mode參數爲負值,將試圖使指定的流是字節定向的;當mode爲0,不作定向,返回標識流的定向值。須要注意兩點:fwide並不改變已定向流的定向;fwide無出錯返回。spa

3、標註輸入、標準輸出和標準錯誤操作系統

  對一個進程預約義了3個流,他們能夠自動地被進程使用,他們是:標註輸入、標註輸出和標準錯誤。這些流與第三章提到的文件描述符STDIN_FILENO、STDOUT_FILENO和STDERR_FILENO所引用相同。這三個標準I/O流經過預約義文件指針stdin、stdout和stderr加以引用。這三個文件指針定義在頭文件<stdio.h>中。指針

4、緩衝rest

  標準I/O庫提供緩衝的目的是進了能減小使用read和write調用的次數。他也對每一個I/O流自動地進行緩衝管理。標準I/O庫提供三種類型的緩衝:code

一、全緩衝:這種狀況下,在填滿標準I/O緩衝區才進行實際I/O操做;對於駐留在磁盤上的文件一般是由標準I/O庫事實全緩衝的。對象

二、行緩衝:在這種狀況下,當在輸入和輸出中遇到換行符時,標準I/O庫執行I/O操做;當流涉及到終端時,一般使用行緩衝。對於行緩衝有兩個限制。第一,由於標準I/O庫用來收集每一行的緩衝區的長度是固定的,因此只要填滿了緩衝區,那麼即便尚未寫一個換行符,也進行I/O操做;第二,任什麼時候候只要經過標準I/O庫從(a)一個不帶緩衝的流,或者(b)一個航緩衝的流(它從內核請求須要數據,其請求的數據可能已在緩衝區)獲得輸入數據,那麼就會沖洗全部行緩衝輸出流。

三、不帶緩衝:標準I/O庫不對字符進行緩衝;標準錯誤流stderr一般是不帶緩衝的,這就是的出錯信息能夠儘快顯示出來,而無論他們是否含有一個換行符。

  ISO C要求下列緩衝特徵:當且僅當標準輸入和標準輸出並不指向交互式設備時,他們纔是全緩衝的;標準錯誤決不會是全緩衝的。大多數系統默認的是:標準錯誤是不帶緩衝的;指向終端設備的流,則是行緩衝的,不然是全緩衝的。

  對於任何一個給定的流,若是咱們並不喜歡這些系統默認,則可調用下列兩個函數中的一個更改緩衝類型:

#include <stdio.h>
void setbuf(FILE *restrict fp, char *restrict buf);
void setvbuf(FILE *restrict fp, cahr *restrict buf, int mode, size_t size);

  setbuf函數能夠打開或關閉緩衝機制。爲了帶緩衝進行I/O,參數buf必須指向一個長度爲BUFSIZ的緩衝區,一般在此以後該流就是全緩衝的,可是若是該流與一個終端設備相關,那麼某些系統也可將其設置爲行緩衝的;爲了關閉緩衝,將buf設置爲NULL。

  setvbuf函數能夠精確地說明所需的緩衝類型。這些用mode參數實現:_IOFBF、_IOLBF、_IONBF,若是指定一個不帶緩衝的流,則忽略buf和size參數;若是指定全緩衝或行緩衝,則buf和size可選擇地指定一個緩衝區及長度。若是該流是帶緩衝的,而buf是NULL,則標準I/O庫將自動地爲該流分配適當長度的緩衝區。若是在一個函數內分配一個自動變量類的標準I/O緩衝區。則從該函數返回以前,必須關閉該流。通常狀況都應由系統選擇緩衝區的長度並自動分配緩衝區,在這種狀況下,標準I/O庫自動釋放緩衝區。

  術語沖洗(flush)說明標準I/O緩衝區的寫操做。緩衝區可由標準I/O例程自動地衝洗,或者能夠調用函數fflush沖洗一個流。flush有兩層意思:在標準I/O庫方面,flush意味着將緩衝區中的內容寫到磁盤上;在終端驅動程序方面,flush標識丟棄已存儲在緩衝區的數據。

#include <stdio.h>
int fflush(FILE *fp);

  次函數是該流全部威脅的數據都被傳送至內核。做爲一種特殊情形,如若fp是NULL,則次函數將致使全部輸出流被沖洗。

5、打開流

#incldue <stdio.h>
FILE *fopen(const char *restrict pathname, const char *restrict type);
FILE *freopen(const char *restrict pathname. const char *restrict type, FILE *restrict fp);
FILE *fdopen(int fd, const char *type);

  上面三個函數均可以打開一個標準的I/O流,區別是:fopen打開一個流;freopen在一個指定的流上打開一個指定的文件,如若該流已經打開,則先關閉該流。如該流已經定向,則使用freopen清除該定向。次函數通常用於將一個指定的文件打開爲一個預約義的流:標準輸入、標準輸出和標準錯誤;fdopen函數娶一個已有的文件描述符,並使一個標準的I/O流與該描述符相結合。

  type參數指定對該I/O流的讀、寫方式,ISO C規定參數能夠有15中不一樣的值(r/w/a/r+/w+/a+)。須要注意的是標準I/O庫是能夠區分文本文件和二進制文件,由於UNIX內核並不對這兩種文件進行區分,因此在UNIX系統環境下指定字符b做爲type的一部分實際上並沒有做用。

  當以讀和寫類型打開一個文件時,具備以下限制:若是中間沒有fflush、fseek、fsetops或rewind,則在輸出的後面不能直接跟隨寫入;若是中間沒有fseek、fsetops或rewind,或者一個輸入操做沒有達到文件尾端,則在輸入操做以後不能跟隨輸出。

  除非流引用終端設備,不然按系統默認,該流被打開時是全緩衝的。若流引用終端設備,則該流是行緩衝的。一旦打開了流,那麼在對該流執行任何操做以前,若是但願,則可以使用setbuf和servbuf改變緩衝的類型。

#include <stdio.h>
int fclose(FILE *fp);

  在該文件被關閉以前,沖洗緩衝中的輸出數據,緩衝區中的任何輸入數據被丟棄,若是標準I/O庫已經爲該流自動分配了一個緩衝區,則釋放該緩衝區。當一個進程正常終止時,則全部帶威脅緩衝數據的標準I/O流都被沖洗,全部打開的標準I/O流都被關閉。

相關文章
相關標籤/搜索