Perl 檔操作

Perl 使用一種叫做檔句柄類型的變數來操作檔。

從檔讀取或者寫入數據需要使用檔句柄。

檔句柄(file handle)是一個I/O連接的名稱。

Perl提供了三種檔句柄:STDIN,STDOUT,STDERR,分別代表標準輸入、標準輸出和標準出錯輸出。

Perl 中打開檔可以使用以下方式:

open FILEHANDLE, EXPR
open FILEHANDLE

sysopen FILEHANDLE, FILENAME, MODE, PERMS
sysopen FILEHANDLE, FILENAME, MODE

參數說明:

  • FILEHANDLE:檔句柄,用於存放一個檔唯一識別字。
  • EXPR:檔案名及檔訪問類型組成的運算式。
  • MODE:檔訪問類型。
  • PERMS:訪問許可權位(permission bits)。

Open 函數

以下代碼我們使用 open 函數以只讀的方式(<)打開檔 file.txt:

open(DATA, "<file.txt");

<表示只讀方式。

代碼中的 DATA 為檔句柄用於讀取檔,以下實例將打開檔並將檔內容輸出:

實例

#!/usr/bin/perl open(DATA, "<file.txt") or die "file.txt 檔無法打開, $!"; while(<DATA>){ print "$_"; }

以下代碼以寫入( > )的方式打開檔 file.txt:

open(DATA, ">file.txt") or die "file.txt 檔無法打開, $!";

>表示寫入方式。

如果你需要以讀寫方式打開檔,可以在 > 或 < 字元前添加 + 號:

open(DATA, "+<file.txt"); or die "file.txt 檔無法打開, $!";

這種方式不會刪除檔原來的內容,如果要刪除,格式如下所示:

open DATA, "+>file.txt" or die "file.txt 檔無法打開, $!";

如果要向檔中追加數據,則在追加數據之前,只需要以追加方式打開檔即可:

open(DATA,">>file.txt") || die "file.txt 檔無法打開, $!";

>> 表示向現有檔的尾部追加數據,如果需要讀取要追加的檔內容可以添加 + 號:

open(DATA,"+>>file.txt") || die "file.txt 檔無法打開, $!";

下表列出了不同的訪問模式:

模式描述
< 或 r只讀方式打開,將檔指針指向檔頭。
> 或 w寫入方式打開,將檔指針指向檔頭並將檔大小截為零。如果檔不存在則嘗試創建之。
>> 或 a寫入方式打開,將檔指針指向檔末尾。如果檔不存在則嘗試創建之。
+< 或 r+讀寫方式打開,將檔指針指向檔頭。
+> 或 w+讀寫方式打開,將檔指針指向檔頭並將檔大小截為零。如果檔不存在則嘗試創建之。
+>> 或 a+讀寫方式打開,將檔指針指向檔末尾。如果檔不存在則嘗試創建之。

Sysopen函數

sysopen 函數類似於 open 函數,只是它們的參數形式不一樣。

以下實例是以讀寫(+<filename)的方式打開檔:

sysopen(DATA, "file.txt", O_RDWR);

如果需要在更新檔前清空文件,則寫法如下:

sysopen(DATA, "file.txt", O_RDWR|O_TRUNC );

你可以使用 O_CREAT 來創建一個新的檔, O_WRONLY 為只寫模式, O_RDONLY 為只讀模式。

The PERMS 參數為八進制屬性值,表示檔創建後的許可權,默認為 0x666

下表列出了可能的模式值:

模式描述
O_RDWR讀寫方式打開,將檔指針指向檔頭。
O_RDONLY只讀方式打開,將檔指針指向檔頭。
O_WRONLY寫入方式打開,將檔指針指向檔頭並將檔大小截為零。如果檔不存在則嘗試創建之。
O_CREAT創建檔
O_APPEND追加檔
O_TRUNC將檔大小截為零
O_EXCL 如果使用O_CREAT時文件存在,就返回錯誤資訊,它可以測試檔是否存在
O_NONBLOCK 非阻塞I/O使我們的操作要麼成功,要麼立即返回錯誤,不被阻塞。

Close 函數

在檔使用完後,要關閉檔,以刷新與檔句柄相關聯的輸入輸出緩衝區,關閉檔的語法如下:

close FILEHANDLE
close

FILEHANDLE 為指定的檔句柄,如果成功關閉則返回 true。

close(DATA) || die "無法關閉檔";

讀寫檔

向檔讀寫信息有以下幾種不同的方式:

<FILEHANDL> 操作符

從打開的檔句柄讀取資訊的主要方法是 <FILEHANDLE> 操作符。在標量上下文中,它從檔句柄返回單一行。例如:

實例

#!/usr/bin/perl print "IT研修網址?\n"; $name = <STDIN>; print "網址:$name\n";

以上程式執行後,會顯示以下資訊,我們輸入網址後 print 語句就會輸出:

當我們使用 <FILEHANDLE> 操作符時,它會返回檔句柄中每一行的列表,例如我們可以導入所有的行到數組中。

實現創建 import.txt 檔,內容如下:

$ cat import.txt
1
2
3

讀取 import.txt 並將每一行放到 @lines 數組中:

實例

#!/usr/bin/perl open(DATA,"<import.txt") or die "無法打開數據"; @lines = <DATA>; print @lines; # 輸出數組內容 close(DATA);

執行以上程式,輸出結果為:

1
2
3

getc 函數

xgetc 函數從指定的 FILEHANDLE 返回單一的字元,如果沒指定返回 STDIN:

getc FILEHANDLE
getc

如果發生錯誤,或在檔句柄在檔末尾,則返回 undef。


read 函數

read 函數用於從緩衝區的檔句柄讀取資訊。

這個函數用於從檔讀取二進位數據。

read FILEHANDLE, SCALAR, LENGTH, OFFSET
read FILEHANDLE, SCALAR, LENGTH

參數說明:

  • FILEHANDLE:檔句柄,用於存放一個檔唯一識別字。
  • SCALAR:存貯結果,如果沒有指定OFFSET,數據將放在SCALAR的開頭。否則數據放在SCALAR中的OFFSET位元組之後。
  • LENGTH:讀取的內容長度。
  • OFFSET:偏移量。

如果讀取成功返回讀取的位元組數,如果在檔結尾返回 0,如果發生錯誤返回 undef。

print 函數

對於所有從檔句柄中讀取資訊的函數,在後端主要的寫入函數為 print:

print FILEHANDLE LIST
print LIST
print

利用檔句柄和 print 函數可以把程式運行的結果發給輸出設備(STDOUT:標準輸出),例如:

print "Hello World!\n";

檔拷貝

以下實例我們將打開一個已存在的檔 file1.txt ,並讀取它的每一行寫入到檔 file2.txt 中:

實例

#!/usr/bin/perl # 只讀方式打開檔 open(DATA1, "<file1.txt"); # 打開新檔並寫入 open(DATA2, ">file2.txt"); # 拷貝數據 while(<DATA1>) { print DATA2 $_; } close( DATA1 ); close( DATA2 );

檔重命名

以下實例,我們將已存在的檔 file1.txt 重命名為 file2.txt,指定的目錄是在 /usr/zaixian/test/ 下:

#!/usr/bin/perl

rename ("/usr/zaixian/test/file1.txt", "/usr/zaixian/test/file2.txt" );

函數 renames 只接受兩個參數,只對已存在的檔進行重命名。

刪除檔

以下實例我們演示了如何使用 unlink 函數來刪除檔:

實例

#!/usr/bin/perl unlink ("/usr/zaixian/test/file1.txt");

指定檔位置

你可以使用 tell 函數來獲取檔的位置,並通過使用 seek 函數來指定檔內的的位置:

tell 函數

tell 函數用於獲取檔位置:

tell FILEHANDLE
tell

如果指定 FILEHANDLE 該函數返回檔指針的位置,以位元組計。如果沒有指定則返回默認選取的檔句柄。

seek 函數

seek()函數是通過檔句柄來移動檔讀寫指針的方式來讀取或寫入檔的,以位元組為單位進行讀取和寫入:

seek FILEHANDLE, POSITION, WHENCE

參數說明:

  • FILEHANDLE:檔句柄,用於存放一個檔唯一識別字。
  • POSITION:表示檔句柄(讀寫位置指針)要移動的位元組數。
  • WHENCE:表示檔句柄(讀寫位置指針)開始移動時的起始位置,可以取的值為0、1、2;分別表示檔開頭、當前位置和文件尾。

以下實例為從檔開頭讀取 256 個位元組:

seek DATA, 256, 0;

檔資訊

Perl 的檔操作也可以先測試檔是否存在,是否可讀寫等。

我們可以先創建 file1.txt 檔,內如如下:

$ cat file1.txt
www.xuhuhu.com

實例

#/usr/bin/perl my $file = "/usr/test/zaixian/file1.txt"; my (@description, $size); if (-e $file) { push @description, '是一個二進位檔' if (-B _); push @description, '是一個socket(套接字)' if (-S _); push @description, '是一個文本檔' if (-T _); push @description, '是一個特殊塊檔' if (-b _); push @description, '是一個特殊字元檔' if (-c _); push @description, '是一個目錄' if (-d _); push @description, '檔存在' if (-x _); push @description, (($size = -s _)) ? "$size 位元組" : ''; print "$file 資訊:", join(', ',@description),"\n"; }

執行以上程式,輸出結果為:

file1.txt 資訊:是一個文本檔, 15 位元組

檔測試操作符如下表所示:

操作符描述
-A檔上一次被訪問的時間(單位:天)
-B 是否為二進位檔
-C 檔的(inode)索引節點修改時間(單位:天)
-M 檔上一次被修改的時間(單位:天)
-O 檔被真實的UID所有
-R 檔或目錄可以被真實的UID/GID讀取
-S 為socket(套接字)
-T 是否為文本檔
-W 檔或目錄可以被真實的UID/GID寫入
-X 檔或目錄可以被真實的UID/GID執行
-b 為block-special (特殊塊)檔(如掛載磁片)
-c 為character-special (特殊字元)檔(如I/O 設備)
-d 為目錄
-e 檔或目錄名存在
-f 為普通檔
-g 檔或目錄具有setgid屬性
-k 檔或目錄設置了sticky位
-l 為符號鏈接
-o 檔被有效UID所有
-p 檔是命名管道(FIFO)
-r 檔可以被有效的UID/GID讀取
-s 檔或目錄存在且不為0(返回位元組數)
-t 檔句柄為TTY(系統函數isatty()的返回結果;不能對檔案名使用這個測試)
-u 檔或目錄具有setuid屬性
-w 檔可以被有效的UID/GID寫入
-x 檔可以被有效的UID/GID執行
-z檔存在,大小為0(目錄恒為false),即是否為空文件,