Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/259.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在PHP中使用文件系统函数,使用UTF-8字符串?_Php_Utf 8_Directory_Filesystems_Mkdir - Fatal编程技术网

如何在PHP中使用文件系统函数,使用UTF-8字符串?

如何在PHP中使用文件系统函数,使用UTF-8字符串?,php,utf-8,directory,filesystems,mkdir,Php,Utf 8,Directory,Filesystems,Mkdir,我无法使用mkdir创建包含UTF-8字符的文件夹: <?php $dir_name = "Depósito"; mkdir($dir_name); ?> 我该怎么办 我使用的是php5,问题是Windows使用utf-16作为文件系统字符串,而Linux和其他系统使用不同的字符集,但通常是utf-8。您提供了一个utf-8字符串,但这在Windows中被解释为另一个8位字符集编码,可能是拉丁语-1,然后在utf-8中用2个字节编码的非ascii字符在Windows中被当作2个字符

我无法使用
mkdir
创建包含UTF-8字符的文件夹:

<?php
$dir_name = "Depósito";
mkdir($dir_name);
?>
我该怎么办


我使用的是php5,问题是Windows使用utf-16作为文件系统字符串,而Linux和其他系统使用不同的字符集,但通常是utf-8。您提供了一个utf-8字符串,但这在Windows中被解释为另一个8位字符集编码,可能是拉丁语-1,然后在utf-8中用2个字节编码的非ascii字符在Windows中被当作2个字符处理

通常的解决方案是将源代码100%保留为ascii格式,并在其他地方使用字符串。

仅使用所需的字符串作为文件名。
urlencode
返回的所有字符都在文件名(NTFS/HFS/UNIX)中有效,然后您可以将文件名
urldecode
返回UTF-8(或者他们使用的任何编码)

注意事项(也适用于以下解决方案):

  • url编码后,文件名必须少于255个字符(可能是字节)
  • UTF-8具有多个字符(使用组合字符)。如果不规范UTF-8,则使用
    glob
    搜索或重新打开单个文件时可能会遇到问题
  • 阿尔法排序不能依赖于
    scandir
    或类似函数。必须
    urldecode
    文件名,然后使用知道UTF-8(和排序规则)的排序算法
更糟糕的解决方案 以下是不太吸引人的解决方案,更复杂,需要更多的注意事项

在Windows上,PHP文件系统包装器需要并返回文件/目录名的ISO-8859-1字符串。这为您提供了两种选择:

  • 在文件名中自由使用UTF-8,但要了解非ASCII字符在PHP之外会显示不正确。非ASCII UTF-8字符将存储为多个ISO-8859-1字符。例如,
    o
    将在Windows资源管理器中显示为
    ó

  • 将文件/目录名限制为。实际上,在文件系统函数中使用UTF-8字符串之前,您将先传递这些字符串,然后再传递这些条目以获取UTF-8中的原始文件名

  • 警告太多了

    • 如果传递给文件系统函数的任何字节与ISO-8859-1中的匹配,那么您就不走运了
    • 在非英语地区,Windows可能使用ISO-8859-1以外的编码。我猜它通常是ISO-8859-#之一,但这意味着您需要使用
      mb\u convert\u编码
      而不是
      utf8\u解码

    这就是为什么您可能只需要创建文件名的原因。

    请尝试使用CodeIgniter Text helper 了解convert_accent_characters()函数,在Unix和Linux下(也可能在OS X下)可以使用它,当前文件系统编码由
    LC_CTYPE
    locale参数给出(请参见函数
    setlocale()
    )。例如,它的计算结果可能类似于
    en_US.UTF-8
    ,这意味着编码是UTF-8。然后可以使用
    fopen()
    创建文件名及其路径,或者使用此编码由
    dir()
    检索文件名

    在Windows下,PHP作为“非Unicode感知程序”运行,然后文件名从文件系统(Windows 2000及更高版本)使用的UTF-16来回转换为选定的“代码页”。控制面板“区域和语言选项”,选项卡面板“格式”设置由
    LC_CTYPE
    选项检索的代码页,而“非Unicode程序的管理->语言”设置文件名的翻译代码页。在西方国家,
    LC_CTYPE
    参数的计算结果类似于
    Language_country.1252
    ,其中1252是代码页,也称为“Windows-1252编码”类似(但不完全相同)到ISO-8859-1。在日本,通常设置932代码页,其他国家也是如此。在PHP下,您可以创建名称可以用当前代码页表示的文件。反之亦然,从文件系统检索到的文件名和路径将使用从UTF-16转换为字节

    此映射是近似的,因此某些字符可能会以不可预测的方式损坏。例如,
    CafféBrillì.txt
    将由
    dir()返回
    作为PHP字符串
    Caff\xE9-Brill\xEC.txt
    如果当前代码页为1252,则与预期一致,而在日语系统中,它将返回近似的
    Caffe-Brilli.txt
    ,因为932代码页中缺少重音元音,然后替换为“最佳匹配”“非重音元音。根本无法翻译的字符将作为
    (问号)检索。通常,在Windows下,没有安全的方法来检测此类瑕疵。”


    更多详细信息请参见我对的回复。

    使用
    com\u dotnet
    PHP扩展,您可以访问Windows的
    Scripting.FileSystemObject
    ,然后使用UTF-8文件/文件夹名执行任何操作

    我将其打包为PHP流包装器,因此非常易于使用:

    首先验证
    com\u dotnet
    扩展是否在
    php.ini
    然后使用以下命令启用包装器:

    stream_wrapper_register('win', 'Patchwork\Utf8\WinFsStreamWrapper');
    
    最后,使用常用的函数(mkdir、fopen、rename等),但在路径前面加上
    win://

    例如:

    <?php
    $dir_name = "Depósito";
    mkdir('win://' . $dir_name );
    ?>
    

    我的一套工具,用于在windowslinux上通过
    PHP
    使用UTF-8文件系统,并与
    兼容。htaccess
    检查文件存在:

    function define_cur_os(){
    
        //$cur_os=strtolower(php_uname());
    
        $cur_os=strtolower(PHP_OS);
    
        if(substr($cur_os, 0, 3) === 'win'){
    
            $cur_os='windows';
    
        }
    
        define('CUR_OS',$cur_os);
    
    }
    
    function filesystem_encode($file_name=''){
    
        $file_name=urldecode($file_name);
    
        if(CUR_OS=='windows'){
    
            $file_name=iconv("UTF-8", "ISO-8859-1//TRANSLIT", $file_name);
    
        }     
    
        return $file_name;
    
    }
    
    function custom_mkdir($dir_path='', $chmod=0755){
    
        $dir_path=filesystem_encode($dir_path);
    
        if(!is_dir($dir_path)){
    
            if(!mkdir($dir_path, $chmod, true)){
    
                //handle mkdir error
    
            }
        }
        return $dir_path;
    }
    
    function custom_fopen($dir_path='', $file_name='', $mode='w'){
    
        if($dir_path!='' && $file_name!=''){
    
            $dir_path=custom_mkdir($dir_path);
    
            $file_name=filesystem_encode($file_name);
    
            return fopen($dir_path.$file_name, $mode);
    
        }
    
        return false;
    
    }
    
    function custom_file_exists($file_path=''){
    
        $file_path=filesystem_encode($file_path);
    
        return file_exists($file_path);
    
    }
    
    function custom_file_get_contents($file_path=''){
    
        $file_path=filesystem_encode($file_path);
    
        return file_get_contents($file_path);
    
    }
    
    其他资源


    您可以使用此扩展来解决您的问题:


    PHP 7.1在Windows上支持UTF-8文件名,而不考虑OEM代码页。

    我不需要写太多,它工作得很好:

    <?php
    $dir_name = mb_convert_encoding("Depósito", "ISO-8859-1", "UTF-8");
    mkdir($dir_name);
    ?>
    

    我还没试过,但你不能用mb\u conver吗
    <?php
    $dir_name = mb_convert_encoding("Depósito", "ISO-8859-1", "UTF-8");
    mkdir($dir_name);
    ?>