本文和大家重點討論一下如何讀寫Perl文件,主要包括打開、關閉Perl文件,讀寫Perl文件,Perl文件的狀態,命令行參數和打開管道六部分內容,希望通過本文的學習你對讀寫Perl文件有深刻的認識。
讀寫Perl文件
一、打開、關閉Perl文件
語法為open(filevar,filename),其中filevar為Perl文件句柄,或者說是程序中用來代表某Perl文件的代號,filename為Perl文件名,其路徑可為相對路徑,亦可為絕對路徑。
open(FILE1,"file1");
open(FILE1,"/u/jqpublic/file1");
打開Perl文件時必須決定訪問模式,在Perl中有三種訪問模式:讀、寫和添加。后兩種模式的區別在於寫模式將原Perl文件覆蓋,原有內容丟失,形式為:open(outfile,">outfile");而添加模式則在原Perl文件的末尾處繼續添加內容,形式為:open(appendfile,">>appendfile")。要注意的是,不能對Perl文件同時進行讀和寫/添加操作。
open的返回值用來確定打開Perl文件的操作是否成功,當其成功時返回非零值,失敗時返回零,因此可以如下判斷:
if(open(MYFILE,"myfile")){
#here'swhattodoifthefileopenedsuccessfully
}
當Perl文件打開失敗時結束程序:
unless(open(MYFILE,"file1")){
die("cannotopeninputfilefile1\n");
}
亦可用邏輯或操作符表示如下:
open(MYFILE,"file1")||die("Couldnotopenfile");
當Perl文件操作完畢后,用close(MYFILE);關閉Perl文件。
二、讀Perl文件
語句$line=<MYFILE>;從Perl文件中讀取一行數據存儲到簡單變量$line中並把Perl文件指針向后移動一行。<STDIN>為標准輸入Perl文件,通常為鍵盤輸入,不需要打開。
語句@array=<MYFILE>;把Perl文件的全部內容讀入數組@array,Perl文件的每一行(含回車符)為@array的一個元素。
三、寫Perl文件
形式為:
open(OUTFILE,">outfile");
printOUTFILE("Hereisanoutputline.\n");
注:STDOUT、STDERR為標准輸出和標准錯誤Perl文件,通常為屏幕,且不需要打開。
四、判斷Perl文件狀態
1、Perl文件測試操作符
語法為:-opexpr,如:
if(-e"/path/file1"){
printSTDERR("Filefile1exists.\n");
}
Perl文件測試操作符
例:
unless(open(INFILE,"infile")){
die("Inputfileinfilecannotbeopened.\n");
}
if(-e"outfile"){
die("Outputfileoutfilealreadyexists.\n");
}
unless(open(OUTFILE,">outfile")){
die("Outputfileoutfilecannotbeopened.\n");
}
等價於
open(INFILE,"infile")&&!(-e"outfile")&&
open(OUTFILE,">outfile")||die("Cannotopenfiles\n");
五、命令行參數
象C一樣,Perl也有存儲命令行參數的數組@ARGV,可以用來分別處理各個命令行參數;與C不同的是,$ARGV[0]是第一個參數,而不是程序名本身。
$var=$ARGV[0];#第一個參數
$numargs=@ARGV;#參數的個數
Perl中,<>操作符實際上是對數組@ARGV的隱含的引用,其工作原理為:
1、當Perl解釋器第一次看到<>時,打開以$ARGV[0]為Perl文件名的Perl文件;
2、執行動作shift(@ARGV);即把數組@ARGV的元素向前移動一個,其元素數量即減少了一個。
3、<>操作符讀取在第一步打開的Perl文件中的所有行。
4、讀完后,解釋器回到第一步重復。
例:
@ARGV=("myfile1","myfile2");#實際上由命令行參數賦值
while($line=<>){
print($line);
}
將把Perl文件myfile1和myfile2的內容打印出來。
六、打開管道
用程序的形式也可以象命令行一樣打開和使用管道(ex:ls>tempfile)。如語句open(MYPIPE,"|cat>hello");打開一個管道,發送到MYPIPE的輸出成為命令"cat>hello"的輸入。由於cat命令將顯示輸入Perl文件的內容,故該語句等價於open(MYPIPE,">hello");用管道發送郵件如下:
open(MESSAGE,"|maildave");
printMESSAGE("Hi,Dave!YourPerlprogramsentthis!\n");
close(MESSAGE);
說明:就會把在filehandle的數據輸入給unix的指令來作處理。
實例1 發郵件
$mailprog="/usr/ucb/mail"; #unix系統上的寄信程序(一定要加絕對路徑)
$who="mqingyi@126.com";
$open(file,"|$mailprog $who")||die"打開失敗\n";
print file "I love you!\n";
print file "I want to see you.\n";
close(file);
就會通過unix系統mail的程序,將FILE這個FILEHANDLE的數據內容寄給$who這個變量所指定的收信人。 我們可以利用open這個函數來設計一個來信批評CGI應用程序,在本書中的下一章中會有詳細的介紹。
==============================
實例2 顯示系統進程數
#!/usr/bin/perl
# returns number of open processes from 'ps' output
open(PROCS,'/bin/ps ax |');
while () {
$procs++;
}
close(PROCS);
$procs--;
print $procs;
===============================
#下面的小例子 僅僅是驗證perl | +unix命令的可能性!
[root@localhost perl]# cat catmai
#!/usr/bin/perl
$catprog="/bin/cat";
open(file,"|$catprog >new")||die"打開失敗\n";
print file "i love you\n";
print file "i want to see you\n";
close(file);
[root@localhost perl]# cat new
i love you
i want to see you
[root@localhost perl]#
打開管道
在 C 中,當你想用標准 I/O 庫打開一個文件時,你要用 “fopen” 函數,當你
想打開一個管道時,你要用 “popen” 函數。但是在 shell 中,你只是用不同
的重定向字符。對於 Perl 也是如此。”open”
的調用方法一樣,只是參數不同了。
如果以管道符號開頭,”open” 啟動一個新的命令,打開一個可寫文件句柄通向
這個命令。你可以向這個句柄中寫入內容,而你所寫的將出現在這個命令的標准
輸出里。例如:
open(PRINTER, “| lpr -Plp1″) || die “can’t run lpr: $!”;
print PRINTER “stuff\n”;
close(PRINTER) || die “can’t close lpr: $!”;
如果末尾的字符是一個管道時,你啟動一個新的命令,打開一個通向這個命令的
可讀文件句柄。這使得這個命令寫入標准輸出的內容可以在你的句柄中讀到的。
open(NET, “netstat -i -n |”) || die “can’t fork netstat: $!”;
while () { } # do something with input
close(NET) || die “can’t close netstat: $!”;
當你試圖打開一個通向或者來自不存在的命令的管道時會發生什么呢?如果可
能,Perl 會檢測到命令失敗,然后照常設置 $!。但是如果命令中包含特殊 的
shell 字符,例如 “>” 或者 “*”,稱為“metacharacters”,Perl 不
會直接執行命令。取而代之的是,Perl 運行 shell,它來試圖運行命令。這意
味着是 shell 得到錯誤指示。在這種情況下,如果 Perl 根本不能運行
shell,”open” 只會指示一個錯誤。參考 “How can I capture STDERR from an
external command?” in perlfaq8 了解如何應付這個問題。在 perlipc
中也有回答。
如果你想打開雙向管道,IPC::Open2 可以處理。參考 “Biderectional
Communication with Another Process” in perlipc。
負號文件
和標准 shell 實用程序一樣,Perl 的 “open” 函數對於只是一個負號的文件
名的處理方法是特殊的。如果你以可讀方式打開負號,實際上是訪問標准輸入。
如果以可寫方式打開,實際上是訪問標准輸出。
如果負號能用作默認的輸入或者輸出,當你打開一個通向或者來自負號的管道會
發生什么呢?它會運行什么默認的命令?僅僅是和你現在運行的腳本一樣!事實
上在 “open” 背后秘密進行了一次 “fork”。更詳細內容請參考 “Safe Pipe
Opens” in perlipc。
2.打開管道
用open函數也可像命令行一樣,打開和使用管道.
語法為:
open(MYVAR, "mode");
mode有如下兩種模式:
"|command" 表示對MYVAR的輸出相當於對command的輸入.
"command|" 表示command的輸出作為對MYVAR的輸入.
例如:
open(FILE1, "who|") or die("Could not open file.\n");
while ($line = )
{
print $line;
}
3.文件重定向
許多UNIX shell可以把標准輸出文件(STDOUT)和標准錯誤文件(STDERR)都重定向到同一個文件.
例如在BASH中,命令`$ foo > file1 2>&1`把輸出到標准輸出和標准錯誤的內容存貯到文件file1中.
用open函數可以實現文件重定向.
如以上命令可以用如下命令實現:
open (STDOUT, ">file1") || die ("open STDOUT failed");
open (STDERR, ">&STDOUT") || die ("open STDERR failed");
文章出處:飛諾網(www.diybl.com):http://www.diybl.com/course/4_webprogram/cgi/perl/20090820/169233.html
一.文件操作
1.打開文件
用open函數可將文件句柄與某文件聯系起來,提供訪問文件的接口,即打開文件.
語法為:
open(FILEVAR, "filepath");
filepath可以有如下三種模式:
"filepath" 以只讀模式打開文件.
">filepath" 以寫模式打開文件.
">>filepath" 以追加模式打開文件,寫和追加的區別在於寫模式將原文件覆蓋,而追加模式則在文件末尾處添加內容.
"+>filepath" 以讀和寫方式打開文件.
"+>>filepath" 以讀和追加方式打開文件.
open的常見用法如下:
if (open(MYFILE, "myfile"))
{
# here's what to do if the file opened successfully
}
當文件打開失敗時結束程序
unless (open (MYFILE, "file1"))
{
die ("cannot open input file file1\n");
}
亦可用邏輯或操作符表示如下:
open (MYFILE, "file1") || die ("Could not open file");
2.打開管道
用open函數也可像命令行一樣,打開和使用管道.
語法為:
open(MYVAR, "mode");
mode有如下兩種模式:
"|command" 表示對MYVAR的輸出相當於對command的輸入.
"command|" 表示command的輸出作為對MYVAR的輸入.
例如:
open(FILE1, "who|") or die("Could not open file.\n");
while ($line = )
{
print $line;
}
3.文件重定向
許多UNIX shell可以把標准輸出文件(STDOUT)和標准錯誤文件(STDERR)都重定向到同一個文件.
例如在BASH中,命令`$ foo > file1 2>&1`把輸出到標准輸出和標准錯誤的內容存貯到文件file1中.
用open函數可以實現文件重定向.
如以上命令可以用如下命令實現:
open (STDOUT, ">file1") || die ("open STDOUT failed");
open (STDERR, ">&STDOUT") || die ("open STDERR failed");
4.讀取文件
語句$line = ;從文件中讀取一行數據存儲到簡單變量$line中並把文件指針向后移動一行.
語句@array = ;把文件的全部內容讀入數組@array,文件的每一行(含回車符)為@array的一個元素.
注:為標准輸入文件,通常為鍵盤輸入,不需要打開.
例如:
open(FILE1, "testfile") or die("Could not open file.\n");
@line = ;
foreach $message (@line)
{
print $message;
}
此外perl還提供以下幾個系統讀函數.
函數read
調用語法:
read (filevar, result, length, skipval);
read函數設計得與UNIX的fread函數等效,可以讀取任意長度的字符存入一個簡單變量.
filevar表示文件變量
result表示存貯結果的簡單變量
length表示讀取的字節數
skipval(可選項),指定讀文件之前跳過的字節數.
返回值為實際讀取的字節數,如果已到了文件末尾,則返回零.如果出錯,則返回空串.
函數sysread
調用語法:
sysread (filevar, result, length, skipval);
更快的讀取數據,與UNIX函數read等效,參數與read相同.
函數getc(讀取單個字符)
調用語法:
$char = getc (infile);
從文件中讀取單個字符。
函數binmode(讀取二進制文件)
調用語法:
binmode (filevar);
當你的系統(如類DOS系統)對文本文件和二進制文件有所區別時使用.必須在打開文件后,讀取文件前使用.
5.寫入文件
寫入文件通常用print,printf和write這三個函數.
print是這三個函數中最簡單的,它向指定的文件輸出,如果未指定,則輸出到當前缺省文件中.
如:
print ("Hello, there!\n");
print OUTFILE ("Hello, there!\n");
第一句輸出到當前缺省文件中,若未調用select,則為STDOUT.
第二句輸出到由文件變量OUTFILE指定的文件中.
printf函數先格式化字符串再輸出到指定文件或當前缺省文件中.
如:
printf OUTFILE ("you owe me %8.2f", $owing);
此語句取出變量$owing的值並替換掉串中的%8.2f,%8.2f是域格式的例子,把$owing的值看作浮點數.
printf的域格式表如下:
%c 單個字符
%d 十進制整數
%e 科學計數法形式的浮點數
%f 普通形式(定點)浮點數
%g 緊縮形式浮點數
%o 八進制整數
%s 字符串
%u 無符號整數
%x 十六進制整數
域格式的注意事項:
A.在格式d,o,u或x中,如果整數值較大或可能較大,可加個l字符,意為長整型,如%ld.
B.%字符后加正整數表示該域的最小寬度,如果寬度不足,則向右對齊,前面用空格補足.如果該正整數以數字0打頭,則補足字符為0.若%字符后為負整數,則結果向右對齊.
C.浮點數域值(%c,%f和%g)中可以指定小數點前后的寬度,如%8.3f意為總寬度為8個字符,小數點后(即小數部分)為3個字符,多出的小數部分四舍五入.
D.在整數,字符或字符串的值域中使用如上的小數形式n.m,n為總寬度,m為輸出結果的最大寬度,這樣就保證了輸出結果前至少有n-m個空格.
write函數使用輸出格式把信息輸出到文件中.
此外perl還提供以下系統寫函數.
函數syswrite
調用語法:
syswrite (filevar, data, length, skipval);
更快的寫入數據,與UNIX函數write等效.
filevar:將要寫入的文件
data:存貯要寫入數據的變量
length:要寫入的字節數
skipval寫操作之前跳過的字節數
最后注意:
有些操作系統在對文件寫入數據時,會先把數據拷貝到一片特殊的內存即緩沖區中,接下來的輸出操作繼續寫入緩沖區直到寫滿.當緩沖區滿了,就把全部數據實際寫入.
象這樣先寫入緩沖區再把整個緩沖區的內容輸出比每次都實際輸出所花費的時間要少得多,因為一般來說,I/O比內存操作慢得多.
在perl中,如果要使當前缺省文件的輸出不進行緩沖,可對$|賦一個非0值.
select (OUTFILE);
$| = 1;
這樣就關閉了對OUTFILE文件寫入的緩沖.
6.關閉文件
close函數可用來關閉已打開的文件.
當用close關閉管道,即重定向的命令時,程序等待重定向的命令結束.
如:
open (MYPIPE, "cat file*|");
close (MYPIPE);
當關閉此文件變量時,程序暫停運行,直到命令cat file*運行完畢.
7.select函數
select函數將通過參數傳遞的文件變量指定為新的當前缺省文件.
如:
select (MYFILE);
這樣,MYFILE就成了當前缺省文件,當對print,write和printf的調用未指定文件時,就輸出到MYFILE中.
8.eof函數
eof函數查看最后一次讀文件操作是否為文件最后一個記錄.如果是,則返回非零值;如果文件還有內容,返回零.
一般情況下,對eof的調用不加括號,因為eof和eof()是等效的.但與<>操作符一起使用時,eof和eof()就不同了.
9.文件定位
tell函數和seek函數配合使用,可輕松實現文件內部的定位.
tell函數的調用格式如下:
tell (filevar);
用於返回從文件頭到當前位置的距離。
seek函數的調用格式如下:
seek (filevar, distance, relative_to);
distance表示移動的字節數,正數向前移動,負數往回移動.
reletive_to的值可為0,1或2.為0時,從文件頭開始移動;為1時,相對於當前位置移動;為2時,相對於文件末尾移動.
命令運行成功返回真,失敗則返回零.
注意:
A.seek和tell不能用於指向管道的文件變量。
B.seek和tell中文件變量參數可使用表達式。
二.目錄操作
1.新建目錄
函數mkdir
調用語法:
mkdir (dirname, permissions);
dirname,將要創建的目錄名,可以為字符串或表達式
permissions,8進制數,指定目錄的訪問權限,其值和意義見下表,權限的組合方法為將相應的值相加.
4000 運行時設置用戶ID
2000 運行時設置組ID
1000 粘貼位
0400 擁有者讀權限
0200 擁有者寫權限
0100 擁有者執行權限
0040 組讀權限
0020 組寫權限
0010 組執行權限
0004 所有人讀權限
0002 所有人寫權限
0001 所有人執行權限
2.改變當前工作目錄
函數chdir
調用語法:
chdir (dirname);
改變當前工作目錄,參數dirname可以為字符串,也可以為表達式.
3.打開目錄
函數opendir
調用語法:
opendir (dirvar, dirname);
打開目錄,與其它函數合用,可查看某目錄中文件列表.
dirvar,目錄變量,與文件變量類似.
dirname,目錄名,可為字符串或表達式.
成功返回真值,失敗返回假.
4.讀取目錄
函數readdir
調用語法:
readdir (mydir);
賦給簡單變量時,每次賦予一個文件或子目錄名,對數組則賦予全部文件和子目錄名.
5.定位目錄列表
函數telldir
調用語法:
location = telldir (mydir);
象在文件中前后移動一樣,telldir和下面的seekdir用於在目錄列表中前后移動.
函數seekdir
調用語法:
seekdir(mydir, location);
location必須為telldir返回的值。
函數rewinddir
調用語法:
rewinddir (mydir);
將讀取目錄的位置重置回開頭,從而可以重讀目錄列表.
6.關閉目錄
函數closedir
調用語法:
closedir (mydir);
關閉打開的目錄.
7.刪除目錄
函數rmdir
調用語法:
rmdir (dirname);
刪除空目錄,成功則返回真,失敗返回假.
三.文件屬性操作
1.文件重定位函數
函數rename
調用語法:
rename (oldname, newname);
改變文件名或移動到另一個目錄中,參數可為字符串或表達式.
2.鏈接和符號鏈接函數
函數link
調用語法:
link (newlink, file);
創建現有文件的鏈接--硬鏈接,file是被鏈接的文件,newlink是被創建的鏈接.
成功返回真,失敗返回假.
當刪除這兩個鏈接中的一個時,還可以用另一個來訪問該文件.
函數symlink
調用語法:
symlink (newlink, file);
創建現有文件的符號鏈接,參數和返回值同上.
當原文件被刪除(如:被unlinke函數刪除),則被創建鏈接不可用.
函數readlink
調用語法:
filename = readlink (linkname);
如果linkname為符號鏈接文件,返回其實際指向的文件,否則返回空串.
函數unlink
調用語法:
num = unlink (filelist);
刪除文件,參數為文件名列表.
返回值為實際刪除的文件數目.
此函數之所以叫unlink而不叫delete是因為它實際所做的是刪除文件的鏈接.
3.文件許可權函數
函數chmod
調用語法:
chmod (permissions, filelist);
改變文件的訪問權限.
permissions為將要設置的權限,filelist為欲改變權限的文件列表.
函數chown
調用語法:
chown (userid, groupid, filelist);
改變文件的屬主.
userid,新屬主的(數字)ID號.
groupid,新的組(數字)ID號,-1為保留原組.
filelist,欲改變屬主的文件列表.
函數.umask
調用語法:
oldmaskval = umask (maskval);
設置文件訪問權限掩碼,返回值為當前掩碼.
4.其它屬性函數
函數truncate
調用語法:
truncate (filename, length);
將文件的長度減少到length字節,如果文件長度已經小於length,則不做任何事.
其中filename可以為文件名,也可以為文件變量.
函數stat
調用語法:
stat (file);
獲取文件狀態,參數file可為文件名也可為文件變量.
返回列表元素依次為:
* 文件所在設備
* 內部參考號(inode)
* 訪問權限
* 硬鏈接數
* 屬主的(數字)ID
* 所屬組的(數字)ID
* 設備類型(如果file是設備的話)
* 文件大小(字節數)
* 最后訪問時間
* 最后修改時間最后改變狀態時間
* I/O操作最佳塊大小
* 分配給該文件的塊數
函數lstat
調用語法:
lstat (file);
與stat類似,區別是將file看作是符號鏈接.
函數utime
調用語法:
utime (acctime, modtime, filelist);
改變文件的最后訪問時間和最后更改時間.
函數fileno
調用語法:
filedesc = fileno (filevar);
返回文件的內部UNIX文件描述,參數filevar為文件變量.