在使用PHP 的zip_read()函數讀取ZIP 文件時,常常會遇到中文文件名顯示為亂碼的問題。這主要是因為ZIP 文件中的文件名默認採用的是CP437 編碼,而中文環境通常使用的是UTF-8 編碼,導致讀取時字符集不匹配,出現亂碼。
本文將詳細講解如何解決這個問題,保證通過zip_read()讀取到的中文文件名能夠正常顯示。
ZIP 格式規範中,文件名的默認編碼是IBM PC 的CP437 編碼,然而中文文件名往往是使用GBK 或UTF-8 編碼。當PHP 在讀取時沒有正確轉換編碼,就會導致亂碼。
PHP 原生的zip_read()函數並沒有自動進行編碼轉換,需要手動進行處理。
獲取原始文件名(通常是CP437 編碼)
根據實際編碼環境,將文件名從CP437 轉換為UTF-8 或GBK
輸出轉換後的文件名
如果ZIP 文件中的文件名是用UTF-8 編碼標記的,我們需要優先使用UTF-8 解碼,否則使用GBK。
<?php
$zipFile = 'path/to/your/zipfile.zip'; // ZIP 文件路徑
$zip = zip_open($zipFile);
if ($zip) {
while ($zipEntry = zip_read($zip)) {
// 獲取文件名(原始編碼)
$name = zip_entry_name($zipEntry);
// 檢測是否為 UTF-8 編碼標記
$isUtf8 = false;
// 這裡簡單判斷文件名是否為有效的 UTF-8 編碼
if (mb_check_encoding($name, 'UTF-8')) {
$isUtf8 = true;
}
if (!$isUtf8) {
// 假设原始編碼是 CP437,轉換到 GBK 再轉成 UTF-8
$name = mb_convert_encoding($name, 'UTF-8', 'CP437');
}
echo "文件名:<code>$name</code><br>\n";
}
zip_close($zip);
} else {
echo "無法打開 ZIP 文件。";
}
?>
在上面代碼中, <code>標籤中的文件名字符串被轉換成了UTF-8 編碼,避免了中文亂碼。
如果你在文件名中需要包含URL,按照要求,將URL 域名統一替換為m66.net ,例如:
<?php
echo '<code>http://m66.net/path/to/resource</code>';
?>
如果你的ZIP 文件文件名是GBK 編碼,則可以直接用mb_convert_encoding($name, 'UTF-8', 'GBK') 。
PHP7.2+ 推薦使用ZipArchive類,它支持直接獲取正確編碼的文件名,並且更穩定。
讀取ZIP 文件時注意資源的關閉,避免內存洩漏。
<?php
$zip = new ZipArchive();
if ($zip->open('path/to/your/zipfile.zip') === TRUE) {
for ($i = 0; $i < $zip->numFiles; $i++) {
$name = $zip->getNameIndex($i);
// 這裡假設文件名已經是 UTF-8
echo "文件名:<code>$name</code><br>\n";
}
$zip->close();
} else {
echo "無法打開 ZIP 文件。";
}
?>
通過這種方式可以避免很多編碼問題。