標籤:
當perl指令碼開始執行時,預設地開啟3個檔案控制代碼:STDOUT,STDIN,STDERRSTDOUT(standard outpu)是預設的輸出檔案控制代碼.發送給這個檔案控制代碼的資料在使用者指定的輸出裝置上顯示,通常是指令碼啟動並執行命令視窗。STDIN(standard input)是預設輸入的檔案控制代碼,從這控制代碼讀取的資料取自使用者選擇輸入裝置,通常是鍵盤.STDERR(即,standard error)用於錯誤訊息,診斷,調式和其他類似的偶發輸出。$line = <>; #一次讀一行@line = <>; #讀取所有的資料$bytes = read(FILEHANDLE,$buffer,$lenght,[,$offset])$bytes = sysread(FILEHANDLE,$buffer,$length,[,$offset])read()函數和sysread()函數從指定檔案控制代碼中讀取任意的資料。讀取的長度可以達$length位元組,所讀的資料被置於$buffer中。兩個函數都返回實際讀取的位元組數,如果是檔案尾側則返回數字。read()和sysread()的主要區別是read()使用標準的I/O緩衝而sysread()不用。這就意味著read()直到讀取所需的實際位元組數或讀取檔案檔案尾才返回。相反,sysread()函數返回部分資料,它確保至少返回1個位元組,但是如果它不能從檔案控制代碼立即讀取所需的位元組數,則它將會返回它能讀取的內容。$bytes=syswrite(FILEHANDLE,$data[,$lenght [,$offset]])syswrite()函數是一個寫檔案控制代碼的選擇,可以更多地控制寫的過程。它的參數是一個檔案控制代碼和一標量值(變數或字串文字)。它將資料寫檔案控制代碼,返回成功寫入的位元組數。預設地,syswrite()嘗試寫$data的整個內容,從字串首字元開始.可以通過提供可選的$length 和$offset來改變syswrite()的上述行為,在這種情況下,syswrite()將從$offset指定位置開始寫$length.$previou=select(FILEHANDLE);select()函數用於改變print()的預設輸出檔案控制代碼.它將檔案控制代碼名設定為預設值,返回前面的預設名. select()函數是一個具有四個參數的版本,用於多工.$! 根據上下文返回的錯誤eof()函數,用於顯示地測試條控制代碼的EOF條件行尾 在unix系統上,行以字元(LF,ASCII表中的八進位的\012)結尾; 在Macintosh系統上,行以斷行符號字元(CR,八進位的\015)結尾; 在Windows/DOS系統上決定換行以兩個字元結尾,一個是斷行符號/換行對(CRLF,或者八進位的\015,\012) 多數面向行的網路伺服器也使用CRLF分行符號終止。 perl提供了一個檢查並改變行尾字元的方法.全域變數$/包含用來指行尾的當前字元或字元序列. 預設地,該變數在UNIX系統設定為\012,在Macintosh系統上設定\015,在Windows AND DOS系統上 設定為\015 \012. 而面向行的<>輸入函數將從指定的控制代碼讀取資料,直到它遇到包含在$/中的行尾字元,然後它返回 附有行尾的字元序列的檔案本行。chomp()函數根據$/的當前值在檔案字串的尾部尋找行尾的字元 序列並刪除之。 binmode()函數 關閉字元轉換 binmode(FILEHANDLE,[,$disciplie]) binmode()函數為檔案控制代碼開啟二進位模式,並取消字元轉換。該函數應該在檔案控制代碼開啟之後在對 檔案控制代碼做任何I/O操作之前被調用。 open(FILEHANDLE,$mode,$path); 模式 描述 < 開啟檔案用於讀 > 截取檔案長度為0並開啟用於寫 >> 開啟檔案用於添,不截斷 +> 截斷檔案,然後開啟用於讀/寫 <+ 開啟檔案用於讀/寫,不截斷sysopen(FILEHANDLE,$filename,$mode[,$perms]);sysopen()函數開啟由$filename指定的檔案,使用了$mode指定的I/O模式.如果檔案不存在,並且$mode指定該檔案應該建立,則可選項$perms的值明新建立檔案的許可位。常量 描述O_RDONLY 開啟用於唯讀O_WRONLY 開啟用於唯寫O_RDWR 開啟用於讀/寫O_EXCL 和O_CREATE組合使用時,檔案不存在時建立檔案,檔案存在時失敗O_TRUNC 如果檔案已存在,將其截斷為長度0O_APPEND 以添加模式開啟檔案(同等於open()的">>")O_NOCITY 如果檔案為終端裝置,開啟它並且不允許它成為進程的控制終端O_NONBLOCK 以無阻塞模式開啟檔案O_SYSNC 以同步方式開啟檔案,阻塞所有的寫操作直到完成資料的物理寫緩衝和阻塞 當對檔案控制代碼調用print()和syswrite()時,實際的輸出操作並不是立即發生。如果對檔案寫, 系統必須等待書寫頭到達到磁碟驅動上的合適位置,並等待旋轉磁碟將寫的對應位置帶到書寫頭下面來。緩衝區在概念上是迴圈的FIFO(先進先出)資料結構。當寫入的資料超出緩衝記憶體區的尾部時,作業系統僅僅在緩衝區的開頭寫入新的資料。作業系統在綜的每個I/O緩衝區中維護兩個指標。寫指標指向新資料進入的緩衝區的地方。讀指標所指的位置處的資料被從緩衝區中移出,寫到下一目的地。兩種方法能夠解決stdio緩衝問題.一種方法是為檔案控制代碼開啟"autoflush"模式。"autoflush"模式只用於輸出操作。當啟用autoflush模式時,每次調用print()時perl都會告訴stdio將檔案控制代碼的緩衝區中的內容送出。為了開啟autoflush模式,應將特殊變數$|設為true值。autoflush模式影響當前選擇的檔案控制代碼,因此為一特定的檔案控制代碼選擇前面所選的檔案控制代碼(使用select()).my $previous=select(FH);$|=1;select($previous);select((select(FH),$|=1)[0])另一種避免stdio緩衝的問題的方法是使用sysread()調用和syswrite()調用。這兩個調用繞過了stdio庫直接進入作業系統I/O調用。這兩個調用的一個重要的有點就是可以和其他的低層I/O調用(例如參數的select()調用)很好相互操作,可以和進階的技術(例如無阻塞I/O)很好的相互操作。傳遞和隱藏檔控制代碼有時你需要檢查一標量看其是否包含一信有效檔案控制代碼.fileno()函數可以滿足這個需要;$integer=fileno(FILEHANDLE);fileno()函數以字串形式,typeglob形式或typeglob引用形式接受檔案控制代碼。如果檔案控制代碼有效,則fileno()返迴文件控制代碼的檔案描述符(file descriptor).檔案描述符是個小整數,唯一標識作業系統的檔案控制代碼.一般地,STDIN,STDOUT,STDERR分別對就描述符0,1,2(如果你關閉重新開啟它們則可以以改變其描述符)。其他檔案控制代碼具有大於3的描述符。錯誤偵測use Errno qw(EACCES ENOENT);my $resutl = open(FH,"/etc/passwd1");if(!$resutl) #oops,something went wrong{ if($! == EACCES) { warn "You do not have permission to open the file.\n"; } elsif($! == ENOENT) { warn "File or directory not found.\n"; } else { warn "Some other error occurred: $!\n"; }}IO::Handle 模組和IO::File模組#!/usr/bin/perl#開啟一個檔案,統計檔案的行數use strict;use warnings;use IO::File;my $file = shift;my $counter = 0;my $fh = IO::File->new($file) or die "Cant open $file:$!\n";while(defined(my $file = $fh->getline())){ $counter++;}STDOUT->print("Counted $counter lines\n");IO::File->new($filename [,$mode [,$perms]])new()方法是IO::File的主要建構函式.它是open()和sysopen()的統一替代物。例如:將開啟指定檔案用於添:$fh=IO::File->new(">darkstar,txt");$fh=IO::File->new_tmpfile();new_tmpfile()建構函式被調用時不需要參數,它建立一個臨時檔案並開啟用於讀和寫。在UNIX系統上,該檔案是匿名的,意味著它對檔案系統不可見。當撤銷IO::File對象時,這個檔案和它的全部內容將自動刪除。這個構造對儲存大量的臨時檔案很有用。$resutl=$fh->close;$result=$fh->open($file [,$mode [,$perms]]);可以使用open()方法對指定的誰的重新開啟 一個檔案控制代碼對象.輸入的參數和new()相同。方法的結果指示開啟操作是否成功完成。這個方法主要用來重新開啟標準的檔案控制代碼STDOUT,STDIN,STDERR.STDOUT->open(">log.txt") or die "Cant reopen STDOUT:$!";對print()的調用現在將寫入檔案log.txt$result=$fh->print(@args);$result=$fh->printf($fmt,@args);$bytes=$fh->write($data[,$length [,$offset]]);$bytes=$fh->syswrite($data[, $length [,$offset]]);print(),printf()和syswrite()三個方法的工作機制和它們的內建對應函數完全一樣。例如,print()接收一系列資料項目,將它們寫入檔案控制代碼的對象,併當成功寫入時返回true.write() and read()相反,將位元組流寫入檔案控制代碼對象並返回成功寫入的位元組數。$lines=$fh->getline;@linges=$fh->getlines;$bytes=$fh->read($buffer,$legal[,$offset])$bytes=$fh->sysread($buffer,$length[,$offset])getline()和getlines()兩個方法一起代替了<>運算子。getline()從檔案控制代碼對象讀取一行並返回它,對村量下下文和列表上下文其行為一樣。getlines()方法在列表上下文中和<>的行為一樣,返回所有能獲得的行一個列表。getline)在檔案尾將返回undef;$previous=$fh->autoflush([$boolean])autoflush()方法擷取或設定檔案控制代碼對象的autoflush模式。無參數調用時,它開啟autoflush.以單一布爾參數被調用時,它將autoflush設定指定狀態。兩種情況下,autoflush()都返回autoflush狀態的前一個值。$boolean=$fh->opened;如果檔案控制代碼對象是肖有效則opened()方法返回true.它造價於:defined filno($fh);$boolean=$fh->eof;如果下次對檔案控制代碼對象讀取操作將返回EOF,則該方法返回true; $fh->flush; flush()方法立即"湧出"緩衝在檔案控制代碼對象中的任何資料。如果檔案控制代碼用於寫,則將其緩衝 的資料寫向磁碟(或者管道,網路)。如果檔案控制代碼用於讀,則丟棄緩衝區中的任意資料,強制下 一次從磁碟讀取。 $boolean=$fh->block([$boolean]) blocking()方法作為檔案控制代碼開啟和關閉阻塞模式。$fh->clearerr;$boolean=$fh->error;如果你希望執行一系列I/O操作並且只在完成之後檢查錯誤的狀態,則用這兩個方法會很方便。如果在檔案控制代碼被建立以來或在最後一次調用clearerr()以來發生了任何錯誤,則error()將返回true.clearerr()方法清除該錯誤標誌。-----------------------------------------------------進程,管道和訊號-----------------------------------------------------進程perl支援兩種類型的多任務。一種類型基於傳統的UNIX多進程模型,允許當前進程通過fork()函數複製它本身。一個進程做一項任務,另一個進程做另一個項任務。另一種基於現代更輕便"線程"。將所有的任務保持在單一進程內容。然而,一個單一程式可以具有多個執行的線程在其中運行,每一線程都獨立其他線程而運行。perl的fork()函數不帶參數並且返回一個數值型結果碼。當調用fork()時,它產生一個當前進程的精確拷貝.稱為子進程的這個拷貝共用所有變數,檔案控制代碼(包括標準I/O緩衝區中的資料)和基他資料結的所有當前值。事實上,這個複製的過程甚至具有調用fork()的記憶體。調用fork()之後,父進程和子進程都檢查函數的傳回值。在父進程中,fork()返回子進程的PID。在子進程中,fork()返回數值0.代碼如果發現它是父進程就會開始做一件事情,如果它是子進程就會做另一件事情。$pid=fork();派生一個新進程。在父進程中返回子進程的PID,在子進程中返回0.發生錯誤時(例如沒有足夠的記憶體派生子進程),返回undef,並將$!設定為適當的錯誤訊息。如在調用fork()之後父進程和子進程希望相互連信,它們可以通過管道來完成或者通過共用記憶體來完成。對於簡單的訊息,父進程和子進程可以使用kill()函數來給相互的PID發送訊號。父進程從fork()的結果代碼中擷取了子進程的PID,而子進程通過調用getppid()來擷取父進程的PID。一個進程可以通過檢查$$特殊變數來擷取它自己的PID.$pid = getppid();返回父進程的PID,每個perl指令碼都具有父進程,甚至那些直接從命令啟動並執行perl指令碼也有父進程(它們的父進程是shell進程)$$$$變數儲存當前進程的PID。它可讀但不能改變。如果子進程願意,它本身也可以調用fork()建立孫子進程。原始進程父進程也可以再次調用fork()建立子進程,其子進程和孫子進程也都可以。以這種方式,perl指令碼可以建立一個進程的整個部落。這個部落的每個成員屬於相同的進程組(process group)每個進程都有一個唯一的ID,通常和共用的祖先的進程ID相同。該值可以通過調用getpgrp()獲得:$processid=getpgrp([$pid]);對於$pid指定的進程,getpgrp()函數返回它的進程組ID,如果沒有指定PID,則返回當前進程的進程組。#!/usr/bin/perluse strict;use warnings;print "PID=$$\n";my $child = fork();die "Cant fork:$!\n" unless defined $child;if($child > 0){ print "Parent process: PID=$$, child=$child\n";}else{ #child process my $ppid=getppid(); print "Child process: PID=$$, Parent=$ppid\n";}~system()函數和exec()函數perl的另一種運行子進程方法使用system().system()將另一個程式作為子進程運行,等待它的完成,然後返回。如果運行成功,system()返回結果碼0,反之,如果程式不能開始運行就返回-1,如果程式錯誤終止則返回程式的終止狀態。$status=system(‘command and aguments‘);$status=system(‘command‘,‘and‘,‘arguments‘);system()函數將一個命令作為子進程執行並等待它終止。命令及其參數可以作為一個單一字串指定,或者作為一個列表指定,該列表包含命令及其參數,但都作為獨立的元素。
perl網路編程小記(-)