Linux基於流的I/O

來源:互聯網
上載者:User

一,流與緩衝    

   流I/O是由C語言的標準函數提供的,這些I/O可以替代系統中提供的read和write函數。事實上流I/O的內部封裝了這兩個基本的檔案讀寫系統調用。使用流I/O在某些程度上來講要方便一些,這些I/O在效率上沒有特別大的差異。

        基於流的操作最終會調用read或者write函數進行操作。為了使程式的運行效率最高,流對象通常會提供緩衝區,以減少調用系統I/O庫函數的次數。

        基於流的I/O提供以下2種緩衝:

1,全緩衝:直到緩衝區填滿,才調用系統I/O函數。對於讀操作來說,直到讀入的內容的位元組數等於緩衝區大小或者檔案以經到達結尾,才進行I/O操作將外存檔案內容讀入緩衝區;對於寫操作來說,直到緩衝區填滿,才進行實際的I/O操作將緩衝區內容寫到外存檔案中。磁碟檔案通常是全緩衝的。

2,行緩衝:直到遇到分行符號\n才調用系統I/O函數。對於讀操作來說,遇到分行符號\n才進行I/O操作,將所讀內容寫入緩衝區;對於寫操作來說,遇到分行符號\n才進行I/O操作,將緩衝區內容寫到外存。由於緩衝區大小是有限制的,所以當緩衝區填滿時即使沒有遇到\n,也同樣會進行實際的I/O操作。標準輸入stdin和標準輸出stdout都預設是行緩衝的。

3,無緩衝:滅有緩衝區,資料會立即讀入或者輸出到外存檔案和裝置上。標準出錯stderr是無緩衝的,這樣也能保證錯誤提示和輸出能及時地反饋給使用者,供使用者排除錯誤。

二,基於檔案流的操作

常用函數:

1,開啟和關閉流

#include<stdio.h>

FILE*fopen(const char * restrict pathname,const char*restrict type);

FILE*fdopen(int fileds,const char*type);

fopen函數的第一個參數表示需要開啟的檔案的路徑,第二個參數表示開啟的方式。

fdopen函數用於在一個已經開啟的檔案上建立一個流,第一個參數是已開啟檔案的檔案描述符,第二個參數是與fopen函數的第二個參數一樣。只有一點不同的是,由於檔案已經開啟,所以fdopen函數不會再建立新檔案,而且也不會將檔案截短為0,這一點要熱別注意,這兩點在開啟檔案描述符的時候已經完成。

       Linux裡用fclose函數關閉一個檔案流,函數原型如下:

#include<stdio.h>

int fclose(FILE *fp);

如果執行成功,函數返回0,失敗返回EOF,這個值在定義在stdio.h中,其值為-1。fclose函數關閉檔案時,該函數會將儲存在記憶體中未來得及寫回到磁碟的檔案內容寫回到磁碟上。瞭解這一點很重要,如果沒有調用fclose函數,就必 須等待記憶體中緩衝區被填滿,由系統將其內容寫回到磁碟上去。對於fclose函數是否需要檢查傳回值的問題困擾著許多程式員。雖然嚴格地說應該檢查所有的 系統調用的傳回值,並且進行錯誤處理,但對於fclose函數出錯的幾率很小,幾乎為0.但如果去關閉一個網路環境中的遠程檔案,fclose函數就有可 能出錯。由於fclose函數在關閉檔案時會將緩衝區的內容寫回到磁碟上,因此fclose函數實際是進行了一個寫操作。在網路環境中,檔案的內容是要通 過網路傳輸到目的主機上並寫入磁碟上的。在這個傳輸過程中,如果網路連結出現問題或者傳輸資料出錯,就會導致檔案內容寫入失敗。這時fclose函數就會 出錯。由此可知,如果在本地關閉一個檔案可以不用檢查傳回值;如果在網路環境中關閉一個檔案,檢查fclose函數的傳回值是有必要的。

三,以字元為單位讀寫資料

       每次讀寫一個字元資料的I/O方式稱為每次一個字元的I/O。Linux下使用fgetc函數獲得一個字元,其函數原型如下:

             #include<stdio.h>

             int fgetc(FILE*fp);

函數如果執行成功則返回該字元的ASCLL值,如果執行失敗,則返回EOF。

Linux環境下使用fputc函數輸出一個字元資料,函數原型如下:

#include<stdio.h>

int fputc(int c,FILE*fp)

第一個參數表示想要輸出的字元的ASCLL值(源),第二個參數表示想要輸出的檔案流(目的地)。

四,以行為單位讀寫資料

      當輸入內容遇到\n時則將流中\n之前的內容送到緩衝區中的I/O方式稱為每一次行的I/O。Linux使用下列函數提供一次讀入一行的功能。

#include<stdio.h>

char*fgets(char *restrict buf,int n,FILE*restrict fp);

char*gets(char*);

fgets函數的第一個參數表示存放讀入的緩衝區,第二個參數n表示讀入的字元個數,此參數的最大值不能超過緩衝區的長度。fgets函數一直讀,直到遇到\n為止,如果在n-1個字元內未遇到分行符號,則唯讀入n-1個字元。最後一個字元用於儲存字串結束標誌\0.需要注意的是fgets函數會將‘\n’分行符號也讀進緩衝區中,因此緩衝區的實際有效內容應該是緩衝區實際位元組數(不包括‘\0’)減1.fgets函數的第三個參數是需要讀入的流對象。

          fgets函數的換回值有以下兩種情況:1,成功讀取一行,返回緩衝區的首地址。2,讀取出錯或者檔案已經到達結尾則返回NULL。

gets函數和fgets函數類似,該函數從標準輸入資料流中讀取一行並將其存入一個緩衝區,並不將‘\n’讀進緩衝區中。gets函數的傳回值和fgets相同。

       Linux 環境下用fputs函數和puts函數實現輸出一行字串,其函數原型如下:

#include<stdio.h>

int fputs(const char*restrict str,FILE *restrict fp);

int puts(const char*str);

fputs函數的第一個參數表示存放輸出內容的緩衝區,第二個參數表示要輸出的檔案。如果執行成功則返回輸出的位元組數,失敗返回-1。puts函數用與向標準輸出輸出一行字串,其參數和fputs函數的第一個參數相同,如果成功輸出,則返回輸出的位元組數,失敗則返回-1,值得注意的是,雖然gets函數不讀入\n,但是puts函數卻輸出\n。fputs和puts函數都不輸出字串的結束符‘\0’。對於I/O來說,fputs函數和fgets函數的搭配是安全又可靠的。

       五,gets函數的漏洞

gets函數和fgets函數最大的不同是gets函數的緩衝區雖然由使用者提供,但是使用者無法指定其一次最多讀入多少個位元組的內容。這一點導致gets函數變成了一個危險的函數。

(文中內容來自《linux c 程式設計大全》吳嶽)

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.