当前位置: 首页> 最新文章列表> 如何解决使用 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 文件。";
}
?>

通过这种方式可以避免很多编码问题。