在開發Web應用程序時,很有可能您會遇到不同格式的文件——CSV數據、密碼文件、XML編碼的內容和不同形式的二進制的數據。您的PHP腳本將需要頻繁地和這些文件交互,從中讀取數據和將數據寫入其中。由於有這麼些格式的文件要處理,所以您就不要意外PHP中有那麼多種類型的內置函數和外部的庫,用來連接和使用幾乎所有您能說出名稱的文件格式。
這篇指南就是關於這樣一種文件格式的,可能應用程序開發者幾乎每天都會遇到這種文件:ZIP格式。一般這種格式是用來通過電子郵件和遠程連接傳輸文件的,能夠將多個文件壓縮到一個檔案文件中,因此,減少了文件的硬盤占據空間,並且能夠更容易地移動它們。PHP通過它的ZZipLib插件和PEAR的Archive_Zip類都可以讀取和創建這些ZIP文件。
我將假設您已經有了正常運行的Apache,安裝了PHP,並且PEAR Archive_Zip class類已經正確安裝了。
注意:您可以直接從網上安裝PEAR Archive_Zip程序包,要麼下載它,還可以利用提供的指示。
創建ZIP檔案文件
讓我們從一個簡單的例子開始:動態地創建一個包括幾個其他文件的ZIP檔案文件。以列表A中的腳本開始。
列表A
< ?php
include ('Archive/Zip.php'); // imports
$obj = new Archive_Zip('test.zip'); // name of zip file
$files = array('mystuff/ad.gif',
'mystuff/alcon.doc',
'mystuff/alcon.xls'); // files to store
if ($obj->create($files)) {
echo 'Created successfully!';
} else {
echo 'Error in file creation';
}
?>
這個腳本非常簡單,但是值得仔細看一下:
首先,第一步是創建一個Archive_Zip類的實例,然後用將要創建的檔案文件的路徑和名稱將其初始化。在這個例子中,檔案文件被命名為test.zip,位於當前目錄下。
接著,初始化一個數組,列出將要被壓縮的文件,和它們在硬盤中的位置一起保存其中;這些位置用絕對或相對術語列入,但是,一個關鍵的要考慮的事項是腳本對那些文件或磁盤的位置要有讀取的權限。
最後,用create()方法通過壓縮和合並指定的文件來實際構建檔案文件。這個方法接受文件列表作為輸入,然後返回一個布爾邏輯值指示檔案文件是否被成功創建。注意腳本在文件被創建的目錄下必須有寫入特權是非常重要的,否則create()方法將失敗;這是一個普遍的,也讓大部分新手失敗的錯誤。
現在,在修改了源文件列表和目標文件位置來反映您的本地系統配置之後,試著運行上面的腳本。如果一切順利的話,Archive_Zip應該可以找到您所列出的、並壓縮到名為test.zip的ZIP檔案文件中的文件。
查看ZIP檔案文件的內容
那麼怎麼樣看到現有的ZIP檔案文件中的內容呢?Archive_Zip lets讓您通過它的listContent()方法也可以做到這一點。下面是一個例子(列表B):
列表B
< ?php
include ('Archive/Zip.php'); // imports
$obj = new Archive_Zip('test.zip'); // name of zip file
$files = $obj->listContent(); // array of file information
foreach ($files as $f) {
foreach ($f as $k => $v) {
echo "$k: $v\n";
}
echo "\n";
}
?>
listContent()的輸出是一個由數組組成的結構數組,每一個數組元素代表檔案文件中的一個單獨文件。通常,每一個元素中保存有相關的信息,例如對應文件的名字、它的索引位置、狀態、大小(壓縮後和壓縮前的)和最近一次修改的時間。用一個循環可以很容易地將這些信息提取出來,還可以像列表B那樣,重定它的格式,使其更好傳輸。下面是輸出的一個示例(列表C):
列表C
filename: mystuff/alcon.xls
stored_filename: mystuff/alcon.xls
size: 113664
compressed_size: 35902
mtime: 1141996836
comment:
folder:
index: 0
status: ok
向現有的ZIP檔案文件中添加新文件
Archive_Zip類的一個有意思的特性就是它可以通過add()方法向現有的檔案文件中添加新的文件。為了說明這一點,讓我們回到test.zip,嘗試對它添加新文件(列表D):
列表D
< ?php
include ('Archive/Zip.php'); // imports
if (file_exists('test.zip')) {
$obj = new Archive_Zip('test.zip'); // name of zip file
} else {
die('File does not exist');
}
$files = array('otherstuff/montecarlo.png'); // additional files to store
if ($obj->add($files)) {
echo 'Added successfully!';
} else {
echo 'Error in file addition';
}
?>
正如您所看到的那樣,向一個現有的檔案文件中添加新文件的程序和創建一個新的檔案文件十分相似:初始化一個新的Archive_Zip對象指向問號代表的檔案文件,創建一個數組代表將要添加的文件的列表,然後將這個數組輸入add()方法。和create()方法一樣,add()返回一個布爾邏輯信號來指示添加是否成功。和前面一樣,一個主要的問題就是別忘了要有足夠的權限:記得確保腳本有適當的權限來讀取源文件,並將新壓縮的檔案文件寫回到硬盤中。
從現有的ZIP檔案文件中刪除文件
和添加文件一樣,您也可以刪除文件。Archive_Zip類具有delete()方法,讓您能夠從現有的檔案文件中移除文件。列表E說明了這一點。.
列表E
< ?php
include ('Archive/Zip.php'); // imports
if (file_exists('test.zip')) {
$obj = new Archive_Zip('test.zip'); // name of zip file
} else {
die('File does not exist');
}
$files = array('mystuff/ad.gif', 'otherstuff/montecarlo.png'); // files to delete
if ($obj->delete(array('by_name' => $files))) {
echo 'Deleted successfully!';
} else {
echo 'Error in file deletion';
}
?>
在這裡,創建了一個待刪除文件的數組,然後將其輸入delete()方法。注意delete()調用中的特殊參數“by_name”:這告訴Archive_Zip只刪除那些與文件名精確匹配的文件。如果刪除成功,delete()方法返回真。
除了這種形式的有選擇的刪除之外,delete()方法也支持對與特定類型或正則表達式相匹配文件的大規模的摧毀。利用“by_ereg”或“by_preg”參數,Perl和PHP的正則表達式都支持。列表F是一個例子,用來說明怎樣用這種方法,通過利用Perl的正則表達式來刪除一個檔案文件中所有的*.doc文件。
列表F
< ?php
include ('Archive/Zip.php'); // imports
if (file_exists('test.zip')) {
$obj = new Archive_Zip('test.zip'); // name of zip file
} else {
die('File does not exist');
}
if ($obj->delete(array('by_preg' => "/.*doc$/"))) { // all DOC files
echo 'Deleted successfully!';
} else {
echo 'Error in file deletion';
}
?>
如以上的例子所示,PEAR的Archive_Zip類用途很多,只需要幾行代碼,就使您能夠執行一些相當復雜的與ZIP文件的交互。但願上面的示例腳本能夠激發起您的靈感,告訴您如何在您的日常開發活動中使用這個類,並讓您對用它進行試驗產生興趣。祝您編程開心!