使用 ZipArchive 的 statIndex 获取压缩文件的文件名时出现乱码无法仅使用 mb_convert_encoding 处理的问题。
下面是不能很好编码的代码和执行结果。
下面的代码将在与 index.php 相同的目录中加载“test.zip”。
“Test.zip”中有“Test.pdf”。
<?php
$zip = new ZipArchive;
if ($zip->open("./テスト.zip") === true) {
$idx = 0;
$zipEntry = $zip->statIndex($idx);
$entryName = $zipEntry['name'];
echo "エンコード無しのファイル名:" . $entryName . "<br>";
$encode = mb_detect_encoding($entryName, "Shift-JIS,EUC-JP");
echo "文字コードチェックした結果:" . $encode . "<br>";
$to = "UTF-8";
$from = "SJIS";
$destName = mb_convert_encoding($entryName, $to, $from);
echo "$from から$to にエンコードした結果:" . $destName . "<br>";
$to = "UTF-8";
$from = "SJIS-win";
$destName = mb_convert_encoding($entryName, $to, $from);
echo "$from から$to にエンコードした結果:" . $destName . "<br>";
$to = "UTF-8";
$from = "CP932";
$destName = mb_convert_encoding($entryName, $to, $from);
echo "$from から$to にエンコードした結果:" . $destName . "<br>";
$to = "SJIS";
$from = "UTF-8";
$destName = mb_convert_encoding($entryName, $to, $from);
echo "$from から$to にエンコードした結果:" . $destName . "<br>";
$to = "SJIS-win";
$from = "UTF-8";
$destName = mb_convert_encoding($entryName, $to, $from);
echo "$from から$to にエンコードした結果:" . $destName . "<br>";
$to = "CP932";
$from = "UTF-8";
$destName = mb_convert_encoding($entryName, $to, $from);
echo "$from から$to にエンコードした結果:" . $destName . "<br>";
$zip->close();
}
?>
エンコード無しのファイル名:âeâXâg.pdf
文字コードチェックした結果:SJIS
SJIS からUTF-8 にエンコードした結果:テ「eテ「Xテ「g.pdf
SJIS-win からUTF-8 にエンコードした結果:テ「eテ「Xテ「g.pdf
CP932 からUTF-8 にエンコードした結果:テ「eテ「Xテ「g.pdf
UTF-8 からSJIS にエンコードした結果:?e?X?g.pdf
UTF-8 からSJIS-win にエンコードした結果:?e?X?g.pdf
UTF-8 からCP932 にエンコードした結果:?e?X?g.pdf
如上所述,无论您编码什么模式,它都不会是原始文件名。 这似乎是由于ZipArchive在statIndexing时自动确定字符代码并应用错误的转换,无法获得Windows环境下使用的字符代码CP932的原始值。 因此,将 ZipArchive::FL_ENC_RAW 添加到 statIndex 的第二个参数。通过这样做,可以防止PHP端的任意字符代码转换,后续转换(mb_convert_encoding)将起作用。 下面是可以很好编码的代码和执行结果。 下面的代码将在与 index.php 相同的目录中加载“test.zip”。 “Test.zip”中有“Test.pdf”。
<?php
$zip = new ZipArchive;
if ($zip->open("./テスト.zip") === true) {
$idx = 0;
$zipEntry = $zip->statIndex($idx, ZipArchive::FL_ENC_RAW);
$entryName = $zipEntry['name'];
echo "エンコード無しのファイル名:" . $entryName . "<br>";
$encode = mb_detect_encoding($entryName, "Shift-JIS,EUC-JP");
echo "文字コードチェックした結果:" . $encode . "<br>";
$to = "UTF-8";
$from = "SJIS";
$destName = mb_convert_encoding($entryName, $to, $from);
echo "$from から$to にエンコードした結果:" . $destName . "<br>";
$to = "UTF-8";
$from = "SJIS-win";
$destName = mb_convert_encoding($entryName, $to, $from);
echo "$from から$to にエンコードした結果:" . $destName . "<br>";
$to = "UTF-8";
$from = "CP932";
$destName = mb_convert_encoding($entryName, $to, $from);
echo "$from から$to にエンコードした結果:" . $destName . "<br>";
$to = "SJIS";
$from = "UTF-8";
$destName = mb_convert_encoding($entryName, $to, $from);
echo "$from から$to にエンコードした結果:" . $destName . "<br>";
$to = "SJIS-win";
$from = "UTF-8";
$destName = mb_convert_encoding($entryName, $to, $from);
echo "$from から$to にエンコードした結果:" . $destName . "<br>";
$to = "CP932";
$from = "UTF-8";
$destName = mb_convert_encoding($entryName, $to, $from);
echo "$from から$to にエンコードした結果:" . $destName . "<br>";
$zip->close();
}
?>
エンコード無しのファイル名:�e�X�g.pdf
文字コードチェックした結果:SJIS
SJIS からUTF-8 にエンコードした結果:テスト.pdf
SJIS-win からUTF-8 にエンコードした結果:テスト.pdf
CP932 からUTF-8 にエンコードした結果:テスト.pdf
UTF-8 からSJIS にエンコードした結果:?e?X?g.pdf
UTF-8 からSJIS-win にエンコードした結果:?e?X?g.pdf
UTF-8 からCP932 にエンコードした結果:?e?X?g.pdf
如上所述,我能够很好地对其进行编码。
就这样。