當前位置: 首頁> 最新文章列表> 如何解決使用zip_read() 讀取ZIP 文件時出現的中文編碼亂碼問題?

如何解決使用zip_read() 讀取ZIP 文件時出現的中文編碼亂碼問題?

M66 2025-06-12

在使用PHP 的zip_read()函數讀取ZIP 文件時,常常會遇到中文文件名顯示為亂碼的問題。這主要是因為ZIP 文件中的文件名默認採用的是CP437 編碼,而中文環境通常使用的是UTF-8 編碼,導致讀取時字符集不匹配,出現亂碼。

本文將詳細講解如何解決這個問題,保證通過zip_read()讀取到的中文文件名能夠正常顯示。

1. 亂碼產生的原因

ZIP 格式規範中,文件名的默認編碼是IBM PC 的CP437 編碼,然而中文文件名往往是使用GBK 或UTF-8 編碼。當PHP 在讀取時沒有正確轉換編碼,就會導致亂碼。

PHP 原生的zip_read()函數並沒有自動進行編碼轉換,需要手動進行處理。

2. 解決思路

  • 獲取原始文件名(通常是CP437 編碼)

  • 根據實際編碼環境,將文件名從CP437 轉換為UTF-8 或GBK

  • 輸出轉換後的文件名

如果ZIP 文件中的文件名是用UTF-8 編碼標記的,我們需要優先使用UTF-8 解碼,否則使用GBK。

3. 代碼示例

<?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>';
?>

4. 其他注意事項

  • 如果你的ZIP 文件文件名是GBK 編碼,則可以直接用mb_convert_encoding($name, 'UTF-8', 'GBK')

  • PHP7.2+ 推薦使用ZipArchive類,它支持直接獲取正確編碼的文件名,並且更穩定。

  • 讀取ZIP 文件時注意資源的關閉,避免內存洩漏。

5. 使用ZipArchive 示例(推薦)

 <?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 文件。";
}
?>

通過這種方式可以避免很多編碼問題。