Perl教學(xué) 第11篇 文件系統(tǒng)之二
發(fā)表時間:2024-06-11 來源:明輝站整理相關(guān)軟件相關(guān)文章人氣:
[摘要]可以看到,這兩行并未按我們想象的順序存貯,為什么呢?我們來分析一下這段程序。第3行重定向標(biāo)準(zhǔn)輸出文件,方法是打開文件file1將它與文件變量STDOUT關(guān)聯(lián),這也關(guān)閉了標(biāo)準(zhǔn)輸出文件。第4行重定向標(biāo)準(zhǔn)錯誤文件,參數(shù)>&STDOUT告訴Perl解釋器使用已打開并與STDOUT關(guān)聯(lián)的文件,...
可以看到,這兩行并未按我們想象的順序存貯,為什么呢?我們來分析一下這段程序。
第3行重定向標(biāo)準(zhǔn)輸出文件,方法是打開文件file1將它與文件變量STDOUT關(guān)聯(lián),這也關(guān)閉了標(biāo)準(zhǔn)輸出文件。第4行重定向標(biāo)準(zhǔn)錯誤文件,參數(shù)>&STDOUT告訴Perl解釋器使用已打開并與STDOUT關(guān)聯(lián)的文件,即文件變量STDERR指向與STDOUT相同的文件。第5、6行分別向STDOUT和STDERR寫入數(shù)據(jù),因為這兩個文件變量指向同一個文件,故兩行字符串均寫到文件file1中,但順序卻是錯誤的,怎么回事呢?
問題在于UNIX對輸出的處理上。當(dāng)使用print(或其它函數(shù))寫入STDOUT等文件時,UNIX操作系統(tǒng)真正所做的是把數(shù)據(jù)拷貝到一片特殊的內(nèi)存即緩沖區(qū)中,接下來的輸出操作繼續(xù)寫入緩沖區(qū)直到寫滿,當(dāng)緩沖區(qū)滿了,就把全部數(shù)據(jù)實際輸出。象這樣先寫入緩沖區(qū)再把整個緩沖區(qū)的內(nèi)容輸出比每次都實際輸出所花費的時間要少得多,因為一般來說,I/O比內(nèi)存操作慢得多。
程序結(jié)束時,任何非空的緩沖區(qū)都被輸出,然而,系統(tǒng)為STDOUT和STDERR分別維護一片緩沖區(qū),并且先輸出STDERR的內(nèi)容,因此存貯在STDERR的緩沖區(qū)中的內(nèi)容line 2出現(xiàn)在存貯在STDOUT的緩沖區(qū)中的內(nèi)容line 1之前。
為了解決這個問題,可以告訴Perl解釋器不對文件使用緩沖,方法為:
1、用select函數(shù)選擇文件
2、把值1賦給系統(tǒng)變量$
系統(tǒng)變量$ 指定文件是否進行緩沖而不管其是否應(yīng)該使用緩沖。如果$ 為非零值則不使用緩沖。$ 與系統(tǒng)變量$~和$^協(xié)同工作,當(dāng)未調(diào)用select函數(shù)時,$ 影響當(dāng)前缺省文件。下例保證了輸出的次序:
1 : #!/usr/local/bin/perl
2 :
3 : open (STDOUT, ">file1") die ("open STDOUT failed");
4 : open (STDERR, ">&STDOUT") die ("open STDERR failed");
5 : $ = 1;
6 : select (STDERR);
7 : $ = 1;
8 : print STDOUT ("line 1\n");
9 : print STDERR ("line 2\n");
10: close (STDOUT);
11: close (STDERR);
程序運行后,文件file1中內(nèi)容為:
line 1
line 2
第5行將$ 賦成1,告訴Perl解釋器當(dāng)前缺省文件不進行緩沖,因為未調(diào)用select,當(dāng)前的缺省文件為重定向到文件file1的STDOUT。第6行將當(dāng)前缺省文件設(shè)為STDERR,第7行又設(shè)置$ 為1,關(guān)掉了重定向到file1的標(biāo)準(zhǔn)錯誤文件的緩沖。由于STDOUT和STDERR的緩沖均被關(guān)掉,向其的輸出立刻被寫到文件中,因此line 1出現(xiàn)在第一行。
4)指定讀寫權(quán)限
打開一個既可讀又可寫的文件方法是在文件名前加上"+>",如下:
open (READWRITE, "+>file1");
此語句打開既可讀又可寫的文件file1,即可以重寫其中的內(nèi)容。文件讀寫操作最好與庫函數(shù)seek和tell一起使用,這樣可以跳到文件任何一點。
注:也可用前綴"+<"指定可讀寫權(quán)限。
5)close函數(shù)
用于關(guān)閉打開的文件。當(dāng)用close關(guān)閉管道,即重定向的命令時,程序等待重定向的命令結(jié)束,如:
open (MYPIPE, "cat file* ");
close (MYPIPE);
當(dāng)關(guān)閉此文件變量時,程序暫停運行,直到命令cat file*運行完畢。
6)print, printf和write函數(shù)
print是這三個函數(shù)中最簡單的,它向指定的文件輸出,如果未指定,則輸出到當(dāng)前缺省文件中,如:
print ("Hello, there!\n");
print OUTFILE ("Hello, there!\n");
第一句輸出到當(dāng)前缺省文件中,若未調(diào)用select,則為STDOUT。第二句輸出到由文件變量OUTFILE指定的文件中。
printf函數(shù)先格式化字符串再輸出到指定文件或當(dāng)前缺省文件中,如:
printf OUTFILE (“You owe me %8.2f", $owing);
此語句取出變量$owing的值并替換掉串中的%8.2f,%8.2f是域格式的例子,把$owing的值看作浮點數(shù)。
write函數(shù)使用輸出格式把信息輸出到文件中,如:
select (OUTFILE);
$~ = "MYFORMAT";
write;
關(guān)于printf和write,詳見《第x章 格式化輸出》。
7)select函數(shù)
select函數(shù)將通過參數(shù)傳遞的文件變量指定為新的當(dāng)前缺省文件,如:
select (MYFILE);
這樣,MYFILE就成了當(dāng)前缺省文件,當(dāng)對print、write和printf的調(diào)用未指定文件時,就輸出到MYFILE中。
8)eof函數(shù)
eof函數(shù)查看最后一次讀文件操作是否為文件最后一個記錄,如果是,則返回非零值,如果文件還有內(nèi)容,返回零。
一般情況下,對eof的調(diào)用不加括號,因為eof和eof()是等效的,但與<>操作符一起使用時,eof和eof()就不同了,F(xiàn)在我們來創(chuàng)建兩個文件,分別叫做file1和file2。file1的內(nèi)容為:
This is a line from the first file.
Here is the last line of the first file.
file2的內(nèi)容為:
This is a line from the second and last file.
Here is the last line of the last file.
下面就來看一下eof和eof()的區(qū)別,第一個程序為:
1: #!/usr/local/bin/perl
2:
3: while ($line = <>) {
4: print ($line);
5: if (eof) {
6: print ("-- end of current file --\n");
7: }
8: }