PHP读取日语文件名时出现问题

4
我有以下代码
<?php
if ($handle = opendir('C:/xampp/htdocs/movies')) {
    while (false !== ($file = readdir($handle))) {
        if ($file != "." && $file != "..") {
            echo $file."<br />\n";
        }
    }
    closedir($handle);
}
?>

当它具有如日语等MB语言时,它无法正确显示,而是显示为kyuukyoku Choujin R ?????~?,而不是kyuukyoku Choujin R 究極超人あ〜る。
有没有办法使其显示正确的名称或使其仍然可以被其他人下载?
谢谢你的帮助 :)

这是不可能的。请参见http://stackoverflow.com/questions/2887909/。 - Artefacto
6个回答

9
我无法确定PHP的情况,但我怀疑它与Python 2之前的基本问题相同(后来添加了对Unicode字符串文件名的特殊支持)。
我认为PHP使用标准C库的“open”等函数处理文件名,这些函数是基于字节的。在Windows(NT)上,这些函数尝试使用系统代码页对真实的Unicode文件名进行编码。对于西方机器,可能是cp1252(类似于ISO-8859-1),对于日本机器,则是cp932(类似于Shift-JIS)。对于任何不存在于系统代码页中的字符,您将得到一个“?”字符,并且无法引用该文件。
为了解决这个问题,PHP需要像Python 3.0一样开始使用Unicode字符串来处理文件名(以及其他所有内容),使用“_wopen”等函数在Windows下获取本地Unicode访问文件名。我预计这将在PHP6中发生,但目前您可能会遇到很多麻烦。您可以将系统代码页更改为cp932以访问文件名,但对于Shift-JIS中没有的任何其他Unicode字符,您仍将获得“?”字符。无论如何,您真的不想使应用程序的内部字符串全部变成Shift-JIS,因为它是一种非常可怕的编码方式。
如果是您自己的脚本选择如何存储文件,我强烈建议使用简单的基于主键的文件名,例如“4356”本地,在数据库中放置实际的文件名,并使用URL中的重写/尾部路径部分提供文件。将用户提供的文件名保留在您自己的本地文件名中很困难,并且即使不必担心Unicode,这也是安全灾难的食谱。

2
+!:"将用户提供的文件名保存在自己的本地文件名中即使不用担心Unicode问题,也很难并且容易导致安全灾难。" - Jon Cram

2
正如@bobince所提到的,PHP会根据“系统区域设置”返回指定编码的文件名,这是非Unicode应用程序使用的。如果字符在当前系统编码中不存在,则文件名将包含“?”,并且无法访问。
您可以尝试安装https://github.com/kenjiuno/php-wfio中的php-wfio.dll,并通过wfio://协议引用文件。

该函数绝对解决了包含日语文件名的目录中 scandir 的问题。它返回完整的日语文件名而不是“?”! - Fenix Lam

0

抱歉 :)

尝试这个:

<?php if ($handle = opendir('C:/xampp/htdocs/movies')) { while (false !== ($file = readdir($handle))) { $filename_utf16 = iconv( "iso-8859-1", "utf-16", $file); if ($filename_utf16 != "." && $filename_utf16 != "..") { echo $filename_utf16 . "<br />\n"; } } closedir($handle); } ?>


0

你错过了另外两个关于$file变量的引用,但这其实是好事,因为我认为我可能发现了一种稍微更有效的方法;试试这个:

<?php
if ($handle = opendir('C:/xampp/htdocs/movies')) {
    while (false !== ($file = readdir($handle))) {
        $file = mb_substr($file, mb_strrpos($file, '/') + 1);
        if ($file != "." && $file != "..") {
            echo $file . "<br />\n";
        }
    }
    closedir($handle);
}
?>

-1

将任何实例的$file替换为mb_substr($file, mb_strrpos($file, '/') + 1),然后您就可以愉快地继续了。多字节编码万岁!


-1

我认为Windows使用UTF-16来存储文件名。因此,可以尝试使用mb_convert_encoding 函数将内部编码转换为输出编码:

// convert from UTF-16 to UTF-8
echo mb_convert_encoding($file, 'UTF-8', 'UTF-16');

也许你需要先更改一些设置(请参见{{link1:mb_get_info}})。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接