在OS-X上(PHP5.2.11)我有一个文件:siësta.doc(以及其他一千个带有Unicode文件名的文件),我想将文件名转换为web-consumable格式(a-zA-Z0-9) )。如果我对上面的文件名进行硬编码,我可以进行正确的转换:
<?php
$file = 'siësta.doc';
echo preg_replace("/[^a-zA-Z0-9.]/u", '_', $file);
// Output: si_sta.doc
?>
但如果我用scandir读取文件名,我就会有奇怪的转换:
<?php
$files = scandir(DIRNAME);
foreach ($files as $file) {
echo preg_replace("/[^a-zA-Z0-9.]/u", '_', $file);
// Output for the file above: sie_sta.doc
}
?>
我试图检测编码,设置编码,用iconv函数转换它。我也试过了mb_函数。但情况更糟。 我做错了什么?
提前致谢
答案 0 :(得分:1)
有趣。经过一些回忆后,我发现OSX将文件名存储为“分解的unicode”(参见http://developer.apple.com/mac/library/qa/qa2001/qa1173.html)。也就是说,“ë”表示为“e”+ diaresis符号(0xcc88)。
答案 1 :(得分:0)
您确实尝试过utf8_encode? (至少在Windows上运行)
<?php
$files = scandir(DIRNAME);
foreach ($files as $file) {
echo preg_replace("/[^a-zA-Z0-9.]/u", '_', utf8_encode($file));
// Output for the file above: sie_sta.doc
}
?>
答案 2 :(得分:0)
问题是windows和php之间的通信。它不可能获得unicode文件名,因为它们依赖于非unicode windows应用程序语言。
最好的解决方案是执行dir命令并获取要处理的信息,但是必须通过cmd执行此操作,并获取windows短名称:
chcp 65001
dir /x c:\test\ > myinfo.txt
它返回:
El volumen de la unidad C es Windows8_OS
El número de serie del volumen es: 14A3-025F
Directorio de C:\test
22/12/2015 22:11 <DIR> .
22/12/2015 22:11 <DIR> ..
22/12/2015 22:12 0 a.txt
22/12/2015 22:10 <DIR> English
22/12/2015 22:10 <DIR> ESPAOL~1 Español
22/12/2015 22:11 <DIR> 8311~1 ру́сский язы́к
22/12/2015 22:10 <DIR> _0B41~1 عربي ,عربى
22/12/2015 22:10 <DIR> 8F4C~1 北方話
1 archivos 0 bytes
7 dirs 839.672.786.944 bytes libres
然后,您可以阅读myinfo.txt以获取原始名称和Windows短名称之间的连接。
有些PHP函数可以使用短名称工作,你可以构建和数组,就好像你需要显示它一样:
$array['short_name']= $original_name;
例如:is_dir, is_file
正常。但是,scandir
或is_readable
也会因短名称而失败。使用这些函数的解决方案是以递归方式重新运行dir命令。
要从txt文件获取信息,您可以使用正则表达式或substr,丢弃前五行和后两行。例如:
for($k=6;$k<(count($array)-2);$k++) ...