Unix 標準I O總結和與檔案I O的比較

2021-07-02 11:57:43 字數 4908 閱讀 4428

我們可以將檔案i/o視為系統呼叫,核心要執行i/o操作,這裡涉及到頁快取(快取記憶體區)的概念,檔案i/o執不執行與快取區有關。

而標準i/o是對系統i/o呼叫的封裝,標準i/o也有快取區、行快取的概念。正是由於這二級的快取模式。導致標準i/o的效率很低。

當開啟乙個流時,標準i/o函式fopen返回乙個指向file物件的指標。該物件通常是乙個結構,它包含了標準i/o庫為管理該流所需的所有資訊,包括:用於實際i/o的檔案描述符、指向用於該緩衝區的指標、緩衝區的長度、當前在緩衝區的字元數以及出錯標誌等。為引用乙個流,需將file指標作為引數傳遞給每個標準i/o函式。

對於標準輸入、標準輸出和標準出錯,他們的檔案描述符對應stfin_fileno、stdout_fileno和stderr_fileno。這三個標準i/o流通過預定義stdin、stdout和stderr加以引用。這三個檔案指標以及標準i/o函式都定義在標頭檔案中。

緩衝標準i/o庫提供緩衝的目的是盡可能減少使用read和write呼叫次數。提供了三種型別的緩衝:

1) 全緩衝:需在填滿標準i/o緩衝區後才進行實際i/o操作。

2) 行緩衝:當在輸入和輸出中遇到換行符時,標準i/o庫執行i/o操作。

3) 不帶緩衝:標準i/o庫不對字元進行緩衝儲存。

一般而言,標準出錯是不帶緩衝的,開啟終端裝置的流是行緩衝的,其他所有流則是全緩衝的。當流是全緩衝,但該緩衝區是區域性填寫時,可用fflush函式沖洗。

可呼叫下面的函式更改緩衝區型別:

#include

void setbuf(file *stream, char *buf);

int setvbuf(file *stream, char *buf, intmode, size_t size);

任何時候,我們都可以強制沖洗乙個流:

#include

int fflush(file *stream);

此函式將使該流所有未寫的資料都被傳送至核心。作為乙個特例,如若fp是null,則此函式將導致所有輸出流被沖洗。

開啟流#include

file *fopen(const char *path, const char*mode);

file *fdopen(int fd, const char *mode);

file *freopen(const char *path, const char*mode, file *stream);

這三個函式的區別是:

1) fopen開啟乙個指定的檔案。

2) fropen在乙個指定的留上開啟乙個指定的檔案,如若該流已經開啟,則先關閉該流。如若該流已經定向,則fopen清除該定向。此函式一般用於將一直指定的檔案開啟為乙個預定義的流:標準輸入、標準輸出或標準錯誤。

3) fdopen獲取乙個現有的檔案描述符,並使乙個標準的i/o流與該描述符相結合。此函式常用於由建立管道和網路通訊函式返回的描述符。因為這些特殊型別的檔案不能用標準i/ofopen函式開啟,所有我們必須先呼叫裝置專用函式以獲得乙個檔案描述符,然後用fopen使乙個標準i/o與該描述符相關聯。

其中的mode引數可以用是以下15種不同的值:

r或rb: 為讀開啟

w或wb: 把檔案截短至0長,或為寫而建立

a或ab: 新增;為在檔案寫開啟,或為寫開啟

r+或r+b或rb+: 為讀和寫開啟

w+或w+b或wb+: 把檔案截短至0,或為讀和寫開啟

a+或a+b或ab+: 為在檔案尾端讀和寫而開啟或建立

#include

int fclose(file *fp);

在檔案被關閉之前,沖洗緩衝區中的輸出資料。如果標準i/o庫已經為該流自動分配了乙個緩衝區,則釋放緩衝區。

讀和寫流

一旦開啟了流,則可在三種不同型別的非格式化i/o中進行選擇,對其讀、寫操作:

1) 每次乙個字元是i/o。一次讀或寫乙個字元,如果流是帶緩衝區的,則標準i/o函式會處理所有緩衝。

2) 每次一行的i/o。如果想要一次讀或寫一行,則使用fgets和fputs。每行都以乙個換行符終止。當呼叫fgets時,應說明能處理的最大行長。

3) 直接i/o。fread和fwrite函式支援這種型別的i/o。

每次乙個字元i/o

輸入函式:

#include

int getc(file *stream);

int fgetc(file *stream);

int getchar(void);

getchar()等價於getc(stdin)。getc和fgetc區別在於getc可被實現為巨集,而fgetc則不能實現為巨集。

不管是出錯還是到達檔案尾端,這三個函式都返回同樣的值。為了區分出錯和到達檔案尾端,必須呼叫ferror和feof函式。

#include

int feof(file *stream);

int ferror(file *stream);

這兩個函式的返回值:若條件為真則返回非0值,否則返回0。

每個流在file物件中維持了兩個標誌:出錯標誌和檔案結束標誌

呼叫clearerr則清除這兩個標誌。

void clearerr(file *stream);

從流讀取資料後,可以呼叫ungetc將字元再壓入回流中。

int ungetc(int c, file *stream);

壓入回流中的字元以後又可以從流中讀出,但讀出的字元順序與壓送回的順序相反。

對於輸出函式:

#include

int putc(int c, file *stream);

int fputc(int c, file *stream);

int putchar(int c);

與輸入函式一樣putchar(c)等效於putc(c, stdout)。putc可實現為巨集。

每次一行i/o

#include

char *fgets(char *s, int size, file*stream);

char *gets(char *s);

fgets從指定的流讀,必須指定緩衝區長度size。此函式一直讀到下乙個換行符為止,但是不超過n-1個字元,讀入的字元被送入緩衝區。該緩衝區以null字元結尾。如若改行(包括最後乙個換行符)的字元數超過n-1,則fgets只返回乙個不完整的行,但是緩衝區總是以null字元結尾。對fgets的下一次呼叫會繼續讀改行。

gets從標準輸入讀。它是乙個不推薦的函式,因為不能指定緩衝區長度,可能造成緩衝區溢位,寫到緩衝區之後的儲存空間中,從而產生不可預料的後果。

fputs和puts提供每次輸出一行的功能。

int fputs(const char *s, file *stream);

int puts(const char *s);

二進位制i/o

#include

size_t fread(void *ptr, size_t size,size_t nmemb, file *stream);

size_t fwrite(const void *ptr, size_tsize, size_t nmemb, file *stream);

以上兩個函式可一次讀或寫整個結構。

定位流有三種方法定位標準i/o流

1) ftell和fseek。這兩個函式要求檔案的位置可以存放到乙個長整形中。

2) ftello和fseeko。他們可以使檔案檔案偏移量不一定使用長整形。他們用off_t資料型別代替了長整形。

3) fgetpos和fsetpos。他們使用抽象資料型別fpos_t記錄檔案的位置。這種資料累心可以定義為記錄乙個檔案的位置所需的長度。

#include

int fseek(file *stream, long offset, intwhence);

long ftell(file *stream);

int fseeko(file *stream, off_t offset, intwhence);

off_t ftello(file *stream);

int fgetpos(file *stream, fpos_t *pos);

int fsetpos(file *stream, fpos_t *pos);

格式化i/o

輸出:#include

int printf(const char *format, ...);

int fprintf(file *stream, const char*format, ...);

int sprintf(char *str, const char *format,...);

int snprintf(char *str, size_t size, constchar *format, ...);

輸入:#include

int scanf(const char *format, ...);

int fscanf(file *stream, const char*format, ...);

int sscanf(const char *str, const char*format, ...);

fileno函式

標準i/o庫最終都要呼叫i/o系統呼叫函式。每個標準i/o流都有乙個與其相關聯的檔案描述符,可以對乙個流呼叫fileno函式以獲得其描述符。

int fileno(file *stream);

臨時檔案

#include

char *tmpnam(char *s);

file *tmpfile(void);

tmpnam函式產生乙個與現有檔名不同的乙個有效路徑名字字串。每次呼叫它,它都產生乙個不同的路徑名,最多呼叫tmp_max次。

tmpfile建立乙個臨時二進位制檔案。

此外還有兩個類似的函式:

#include

char *tempnam(const char *dir, const char*pfx);

int mkstemp(char *template);

UNIX 檔案I O總結

輸入是從i o裝置拷貝資料到主存,輸出是從主存拷貝資料到i o裝置。乙個檔案就是乙個位元組序列。所有的i o裝置,如網路 磁碟 和終端,都被模型化為檔案,而所有的輸入和輸出都被當做想對應的檔案的讀寫來執行。1 iso c的i o操作是帶快取的,而posix標準的i o操作是指真正發生了系統呼叫,是不...

檔案標準標準IO與檔案IO 的區別

首先宣告,我是乙個菜鳥。一下文章中出現技術誤導情況蓋不負責 先來了解下什麼是標準 以及檔案 標準 標準i o是ansi c建立的乙個標準i o模型,是乙個標準函式包和stdio.h標頭檔案中的定義,擁有必定的可移植性。標準io庫處理很多細節。例如快取分配,以優化長度執行io等。標準的io供給了三種型...

Unix標準IO檔案流及緩衝型別

在檔案io相關函式的一節中,我們所有的i o函式都是圍繞著檔案描述符來操作的,當開啟乙個檔案的時候,即返回乙個檔案描述符,然後該檔案描述符用於後續的檔案操作。而對於標準io庫,對於檔案的操作都是圍繞這 檔案流 file stream 進行的。當我們使用標準io庫開啟或建立乙個檔案的時候,我們已經使乙...