本章用於解析c語言標準i/o庫,之所以在unix類系統的程式設計中會介紹c語言標準庫,主要是因為unix和c之間具有密不可分的關係。
標準i/o庫相比於作業系統的i/o庫,具有更高的效率和可移植性,前者是因為標準i/o庫提供了緩衝和塊長度優化功能,後者是因為使用標準i/o庫的**不僅能在各unix系統上移植,也能在支援標準c的非unix系統上移植。
一、基本概念
流和file物件
unix系統i/o是建立在檔案描述符的抽象概念上的,而標準i/o庫則是建立在流的概念上的。當使用標準i/o庫開啟乙個檔案進行讀寫時,會建立乙個流,該流與將要開啟的檔案進行關聯,通過對抽象流的讀寫來間接讀寫檔案。
標準輸入、標準輸出和標準錯誤
unix系統的shell中會預設為程序開啟3個檔案描述符:標準輸入0、標準輸出1和標準錯誤2。但它們是檔案描述符的可閱讀巨集,iso c標準i/o是無法使用的,為此iso c標準i/o定義了三個另外的名字來引用它們,分別是:stdin、stdout、strerr。它們在標頭檔案中被定義。實際上stdin_fileno、stdout_fileno、stderr_fileno分別對應stdin、stdout、strerr。
緩衝
對於unix系統來說,標準i/o庫最終是建立在系統呼叫的read()和write()上的。而unix系統的read()和write()是不帶緩衝的。為了提供效率,標準i/o庫提供了緩衝管理。
對於需要立即執行完成的標準讀寫操作,我們可以強制使用fflush()函式來重新整理流的緩衝區。其函式宣告如下:
1 #include 23int fflush(file *__stream);45
/*例子
*/6 fflush(stream);
二、標準i/o函式
1 #include 23/*1. 開啟流
*/4 file *fopen(const
char * __filename, const
char *__modes);
5 file *freopen(const
char * __filename, const
char * __modes, file *__stream);
6 file *fdopen(int __fd, const
char *__modes);7/*
fopen()用於開啟指定路徑的檔案 */8
/*freopen()在指定流上關聯指定的檔案。如流已經開啟,則重新開啟;如流已定向,則清除定向。該函式通常用來重定向標準輸入、標準輸出和標準錯誤 */9
/*fdopen()用於將乙個已有的檔案描述符與乙個標準i/o流關聯。該函式常在建立管道或者網路socket得到的描述符上
*/10
11/*
2. 讀/寫流
*/12
/*2.1 位元組i/o
*/13
int getc(file *__f);
14int fgetc(file *__f);
15int getchar(void
);16
/*這三個函式一次只讀取乙個unsigned char,然後轉換為int,在讀取乙個字元後,流自動移動到下乙個字元,然後再次呼叫函式時會返回相對於上一次字元的下乙個位置上的字元
*/17
18int putc(int __c, file *__f);
19int fputc(int __c, file *__f);
20int putchar(int
__c);
21/*
這三個函式成功返回__c,失敗返回null。這三個函式一次只寫入乙個unsigned char,如果傳遞的值超過256的int型別實參給函式,那麼超出範圍的會被截斷
*/22
23/*
2.2 行i/o,遇到換行符位置
*/24
char *gets(char *__s);
25char *fgets(char* __s, int __n, file*__f);
26/*
gets()函式建議不要使用,因為此函式會導致快取區溢位
*/27
28int fputs(const
char* __s, file*__f);
29int puts(const
char*__s);
3031
/*2.3 二進位制i/o
*/32 size_t fread(void* __ptr, size_t __size, size_t __n, file*__f);
33 size_t fwrite(const
void* __ptr, size_t __size, size_t __n, file*__f);
34/*
這兩個函式的返回值都是讀或寫的物件數量。引數中的__size是物件的大小,即sizeof計算得到的大小;__n是物件的數量
*/35
36/*
3. 定位流
*/37
int fseek(file *__f, long
int __off, int
__whence);
3839
/*4.關閉流
*/40
int fclose(file *__f);
**中的fopen()函式的第二個引數有以下幾種模式:
r 以唯讀方式開啟檔案,該檔案必須存在
r+ 以讀/寫方式開啟檔案,該檔案必須存在
rb+ 以讀/寫方式開啟乙個二進位制檔案,只允許讀/寫資料
rt+ 以讀/寫方式開啟乙個文字檔案,允許讀和寫
w 開啟只寫檔案,若檔案存在則檔案長度清為零,即該檔案內容會消失;若檔案不存在則建立該檔案
w+ 開啟可讀/寫檔案,若檔案存在則檔案長度清為零,即該檔案內容會消失;若檔案不存在則建立該檔案
a 以附加的方式開啟只寫檔案。若檔案不存在,則會建立該檔案;如果檔案存在,則寫入的資料會被加到檔案尾後,即檔案原先的內容會被保留(eof 符保留)
a+ 以附加方式開啟可讀/寫的檔案。若檔案不存在,則會建立該檔案,如果檔案存在,則寫入的資料會被加到檔案尾後,即檔案原先的內容會被保留(eof符不保留)
wb 以只寫方式開啟或新建乙個二進位制檔案,只允許寫資料
wb+ 以讀/寫方式開啟或新建乙個二進位制檔案,允許讀和寫
wt+ 以讀/寫方式開啟或新建乙個文字檔案,允許讀和寫
at+ 以讀/寫方式開啟乙個文字檔案,允許讀或在文字末追加資料
ab+ 以讀/寫方式開啟乙個二進位制檔案,允許讀或在檔案末追加資料
常用的有r+,rt+,at+等
**中的gets()會導致快取區溢位,盡量不要使用。同樣會導致快取區溢位的函式有strcpy()、strcat()等
示例**:
1 file *stream =null;2char buf[100] = "
hello world\n";
3int ret = 0;4
5 stream = fopen("
a.txt
", "w+"
);67 fwrite(buf, sizeof(char
), strlen(buf), stream);
8 fseek(stream, 0, seek_set); /*
whence可選為seek_set、seek_cur、seek_end
*/9 memset(buf, 0, sizeof
(buf));
10 ret = fread(buf, sizeof(char), sizeof
(buf), stream);
11if
(ret)
1415 fclose(stream);
下一章 第七章:程序環境
第五章 標準I O庫
1.fwide函式 用於設定流的定向。int fwide file fp,int mode 若流是寬定向,返回正值 是位元組定向,返回負值 是未定向,返回0。如若mode是負值,則函式試圖使指定的流是位元組定向的 如果mode是正值,則函式試圖使制定的流是寬定向的 若mode引數值為0,函式不試圖設...
APUE筆記 第五章 標準I O庫
2.流和相關函式 3.格式化i o 4.fileno 函式 5.tmpnam 和tmpfile 函式 標準i o庫是在系統呼叫函式基礎上構造的。ansi c要求下列快取特徵 1 當且僅當標準輸入和標準輸出並不涉及互動作用裝置時,它們才是全快取的。2 標準出錯決不會是全快取的。1.1全快取 在這種情況...
python第五章 Python學習(第五章)
記錄所有的名片字典 card list defshow menu 顯示資訊 print 50 print 歡迎使用 名片管理系統 v1.0 print print 1.新增名片 print 2.顯示全部 print 3.搜尋名片 print print 0.退出系統 print 50 defnew ...