天天看點

《UNIX環境進階程式設計(第3版)》——1.5 輸入和輸出

本節書摘來自異步社群《unix環境進階程式設計(第3版)》一書中的第1章,第1.5節,作者:【美】w. richard stevens , stephen a.rago著,更多章節内容可以通路雲栖社群“異步社群”公衆号檢視

1.檔案描述符

檔案描述符(file descriptor)通常是一個小的非負整數,核心用以辨別一個特定程序正在通路的檔案。當核心打開一個現有檔案或建立一個新檔案時,它都傳回一個檔案描述符。在讀、寫檔案時,可以使用這個檔案描述符。

2.标準輸入、标準輸出和标準錯誤

按慣例,每當運作一個新程式時,所有的shell都為其打開3個檔案描述符,即标準輸入(standard input)、标準輸出(standard output)以及标準錯誤(standard error)。如果不做特殊處理,例如就像簡單的指令ls,則這3個描述符都連結向終端。大多數shell都提供一種方法,使其中任何一個或所有這3個描述符都能重新定向到某個檔案,例如:

<code>ls &gt; file.list</code>

執行ls指令,其标準輸出重新定向到名為file.list的檔案。

3.不帶緩沖的i/o

函數open、read、write、lseek以及close提供了不帶緩沖的i/o。這些函數都使用檔案描述符。

執行個體

如果願意從标準輸入讀,并向标準輸出寫,則圖1-4中所示的程式可用于複制任一unix普通檔案。

圖1-4 将标準輸入複制到标準輸出

頭檔案(apue.h中包含了此頭檔案)及兩個常量stdin_fileno和stdout_fileno是posix标準的一部分(下一章将對此做更多的說明)。頭檔案包含了很多unix系統服務的函數原型,例如圖1-4程式中調用的read和write。

兩個常量stdin_fileno和stdout_fileno定義在頭檔案中,它們指定了标準輸入和标準輸出的檔案描述符。在posix标準中,它們的值分别是0和1,但是考慮到可讀性,我們将使用這些名字來表示這些常量。

3.9節将詳細讨論buffsize常量,說明它的各種不同值将如何影響程式的效率。但是不管該常量的值如何,此程式總能複制任一unix普通檔案。

read函數傳回讀取的位元組數,此值用作要寫的位元組數。當到達輸入檔案的尾端時,read傳回0,程式停止執行。如果發生了一個讀錯誤,read傳回−1。出錯時大多數系統函數傳回−1。

如果将該程式編譯成标準名稱的a.out檔案,并以下列方式執行它:

<code>./a.out &gt; data</code>

那麼标準輸入是終端,标準輸出則重新定向至檔案data,标準錯誤也是終端。如果此輸出檔案并不存在,則shell會建立它。該程式将使用者鍵入的各行複制到标準輸出,鍵入檔案結束符(通常是ctrl+d)時,将終止本次複制。

若以下列方式執行該程式:

<code>./a.out &lt; infile &gt; outfile</code>

會将名為infile檔案的内容複制到名為outfile的檔案中。

4.标準i/o

标準i/o函數為那些不帶緩沖的i/o函數提供了一個帶緩沖的接口。使用标準i/o函數無需擔心如何選取最佳的緩沖區大小,如圖1-4中的buffsize常量的大小。使用标準i/o函數還簡化了對輸入行的處理(常常發生在unix的應用程式中)。例如,fgets函數讀取一個完整的行,而read函數讀取指定位元組數。在5.4節中我們将了解到,标準i/o函數庫提供了使我們能夠控制該庫所使用的緩沖風格的函數。

我們最熟悉的标準i/o函數是printf。在調用printf的程式中,總是包含(在本書中,該頭檔案包含在apue.h中),該頭檔案包括了所有标準i/o函數的原型。

圖1-5程式的功能類似于前一個調用了read和write的程式,5.8節将對此程式進行更詳細的說明。它将标準輸入複制到标準輸出,也就能複制任一unix普通檔案。

圖1-5 用标準i/o将标準輸入複制到标準輸出

函數getc一次讀取一個字元,然後函數putc将此字元寫到标準輸出。讀到輸入的最後一個位元組時,getc傳回常量eof(該常量在中定義)。标準i/o常量stdin和stdout也在頭檔案中定義,它們分别表示标準輸入和标準輸出。