在文件I/O中,要從一個(gè)文件讀取數(shù)據(jù),應(yīng)用程序首先要調(diào)用操作系統(tǒng)函數(shù)并傳送文件名,并選一個(gè)到該文件的路徑來打開文件。該函數(shù)取回一個(gè)順序號(hào),即Perl文件句柄(filehandle),該P(yáng)erl文件句柄對于打開的文件是唯一的識(shí)別依據(jù)。要從文件中讀取一塊數(shù)據(jù),應(yīng)用程序需要調(diào)用函數(shù)ReadFile,并將Perl文件句柄在內(nèi)存中的地址和要拷貝的字節(jié)數(shù)傳送給操作系統(tǒng)。當(dāng)完成任務(wù)后,在通過調(diào)用系統(tǒng)函數(shù)來關(guān)閉該文件。
除了你模仿唯我論者哲學(xué)家編寫一個(gè)人工智能程序,你的程序使用不和外界通訊的方法。在班級例子中的第三和四行,你將看到"GRADES",這是引用另一個(gè)Perl文件的數(shù)據(jù)類型,稱為據(jù)柄(filehandle)。一個(gè)句柄就是你給一個(gè)文件,設(shè)備,管套(socket)或管道的一個(gè)名字,以便幫助你記住你正處理的名字,并隱藏某些緩存等的復(fù)雜性。(在內(nèi)部,句柄類似C++語言的流(streams),或BASIC中的I/O通道)句柄使你從不同的地方輸入和輸出給不同的地方都較容易。使Perl成為好語言的一個(gè)原因是它能和多個(gè)文件通訊并一次處理他們。對外部對象有好的符號(hào)名字是一個(gè)好語言的一個(gè)組成部分[1]。
其他使Perl是一個(gè)好語言的是:它是8位的,是可嵌入的,你能通過擴(kuò)展模式在Perl中嵌入其他程序。它是簡明的,網(wǎng)絡(luò)上容易使用。環(huán)境上是清楚的,容易對話。你能以許多不同的方法引用它(就象前面看到的)??傊?,語言本身不是如此嚴(yán)格的結(jié)構(gòu),以至于你不能使它超出你的問題。又回到TMTOWTDI。
你創(chuàng)建一個(gè)句柄,并通過open函數(shù)把它和一個(gè)文件聯(lián)結(jié)。open有兩個(gè)參數(shù):句柄和你想與它聯(lián)結(jié)的一個(gè)文件名。Perl也給出一些預(yù)定義(和預(yù)打開的)句柄。STDIN是你程序的正常輸入通道,而STDOUT是你程序的正常輸出的通道。STDERR是一個(gè)附加的輸出通道,以便當(dāng)把輸入轉(zhuǎn)為輸出時(shí),程序能給出一些說明[2]。
一般地,這些句柄和你的終端聯(lián)結(jié),所以你能輸入你的程序并能看到,但他們也可以和文件聯(lián)結(jié)。Perl能給你這些預(yù)定義句柄,因?yàn)槟愕牟僮飨到y(tǒng)已提供這些。在UNIX下,進(jìn)程從他的父進(jìn)程(一般是一個(gè)shell)繼承標(biāo)準(zhǔn)輸入,輸出和錯(cuò)誤。一個(gè)shell的責(zé)任之一是建立這些I/O流,以便子進(jìn)程不必考慮這些)。
既然你能為各種目的(輸入,輸出,管道)使用open函數(shù)創(chuàng)建句柄,你就必須能指明你要做什么。就象在UNIX命令行一樣,你給文件名簡單地加些字符。
復(fù)制代碼 代碼如下:
open(SESAME,"filename");#從已存在的文件讀
open(SESAME,"filename");#顯式地,同上面
open(SESAME,">filename");#創(chuàng)建一個(gè)文件并對它寫
open(SESAME,">>filename");#對已有的文件接著寫
open(SESAME,"|output-pipe-command");#建立一個(gè)輸出過濾
open(SESAME,"input-pipe-command|");#建立一個(gè)輸入過濾
就象你看到的,你可以任意選名字。一旦打開句柄SESAME,它就能被用于存取文件或管道,直到它被顯式地關(guān)閉(用close(SESAME)),或?qū)ν痪浔囊幌盗衞pen把這個(gè)句柄和另一文件聯(lián)結(jié)[3]。
打開一個(gè)已打開的句柄是隱式地關(guān)閉第一個(gè)文件,使它對Perl文件句柄不可取,并打開一個(gè)不同的文件。你必須小心這是你真正想做的。有時(shí),偶然碰巧,比如,當(dāng)你open($handle,$file)時(shí),$handle正好包含空串(null)。確認(rèn)設(shè)置$handle為某個(gè)單一個(gè)量,否則你將對空句柄打開一個(gè)新的文件。
一旦你已為輸入打開一個(gè)句柄(或你使用STDIN),你就能使用"行讀操作">,讀一行。這個(gè)也以鉆石操作聞名,因?yàn)樗男螤?。這個(gè)鉆石操作包含你想讀的句柄()[4]。使用STDID句柄讀用戶提供的答案,如下:
空鉆石操作>,將從命令行指定的所有文件讀,如果沒有指定,從STDIN讀。(這是許多UNIX"過濾"程序的標(biāo)準(zhǔn)行為)
復(fù)制代碼 代碼如下:
printSTDOUT"Enteranumber:";#請求輸入一個(gè)數(shù)
$number=STDIO>;#輸入一個(gè)數(shù)
printSTDOUT"Thenumberis$number";#輸出這個(gè)數(shù)
你明白我們給你的例子嗎?在print語句中STDOUT做什么?這就是你使用一個(gè)輸出句柄的方法之一。一個(gè)句柄可以作為print語句的第一個(gè)參數(shù),如果存在,告訴往哪兒輸出。在例子中,句柄是冗余的,因?yàn)檩敵鲆呀?jīng)是STDOUT。對于輸入的缺省是STDIN,對于輸出的缺省是STDOUT。(在班級例子的18行,我們?yōu)楸苊馐鼓慊煜?我們省略了。)
我們也有一件事使你不明白。如果你試上面的例子,你可以注意到你得到一個(gè)特別的空行。因?yàn)樽x時(shí)沒有自動(dòng)地從你的輸入行中刪除換行符(newline)(例如,你輸入"9")。對于這些情況,當(dāng)你想刪除換行符時(shí),Perl提供chop和chomp函數(shù)。chop將不加區(qū)別地刪除(并返回)傳給它的最后一個(gè)字符,而chomp只刪除記錄標(biāo)識(shí)的末尾(一般地是""),并返回這樣刪除的字符數(shù)。