代码之家  ›  专栏  ›  技术社区  ›  itarato Randy Sugianto 'Yuku'

preg\u replace()和scandir()的编码问题

  •  0
  • itarato Randy Sugianto 'Yuku'  · 技术社区  · 14 年前

    在OS-X(PHP5.2.11)上,我有一个文件:sista.doc(以及其他具有Unicode文件名的文件),我想将文件名转换为web可消费格式(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函数。但情况更糟。

    提前谢谢

    3 回复  |  直到 14 年前
        1
  •  2
  •   user187291    14 年前

    很有趣。经过一段时间的研究,我发现OSX将文件名存储为“分解的unicode”(参见 http://developer.apple.com/mac/library/qa/qa2001/qa1173.html

        2
  •  0
  •   Andre Backlund    14 年前

    你试过utf8编码吗(至少在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
      }
    ?>
    
        3
  •  0
  •   Juanjo    9 年前

    问题是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

    for($k=6;$k<(count($array)-2);$k++) ...