我不能mkdir
用 UTF-8 字符创建文件夹:
<?php
$dir_name = "Depósito";
mkdir($dir_name);
?>
当我在 Windows 资源管理器中浏览此文件夹时,文件夹名称如下所示:
Depósito
我应该怎么办?
我正在使用 php5
我不能mkdir
用 UTF-8 字符创建文件夹:
<?php
$dir_name = "Depósito";
mkdir($dir_name);
?>
当我在 Windows 资源管理器中浏览此文件夹时,文件夹名称如下所示:
Depósito
我应该怎么办?
我正在使用 php5
只是urlencode
需要作为文件名的字符串。 从返回的所有字符urlencode
在文件名(NTFS/HFS/UNIX)中都是有效的,然后您可以只urldecode
将文件名返回为 UTF-8(或它们所在的任何编码)。
注意事项(也适用于以下解决方案):
glob
或重新打开单个文件。scandir
或类似的功能进行 alpha 排序。您必须urldecode
在文件名之后使用支持 UTF-8(和排序规则)的排序算法。以下是不太有吸引力的解决方案,更复杂且有更多警告。
在 Windows 上,PHP 文件系统包装器期望并返回文件/目录名称的 ISO-8859-1 字符串。这为您提供了两种选择:
在您的文件名中自由使用 UTF-8,但要了解非 ASCII 字符在 PHP 之外会显得不正确。非 ASCII UTF-8 字符将存储为多个单个ISO-8859-1 字符。例如ó
,将ó
在 Windows 资源管理器中显示。
将您的文件/目录名称限制为ISO-8859-1 中可表示的字符。在实践中,您将在文件系统函数中使用它们之前传递您的 UTF-8 字符串utf8_decode
,并传递条目scandir
让您通过utf8_encode
以获取 UTF-8 中的原始文件名。
警告多多!
mb_convert_encoding
而不是utf8_decode
.这个噩梦就是为什么你应该只音译来创建文件名。
在 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 转换为字节。
此映射是近似的,因此某些字符可能会以不可预知的方式被破坏。例如,如果当前代码页是 1252,它将按预期Caffé Brillì.txt
返回dir()
为 PHP 字符串Caff\xE9 Brill\xEC.txt
,而在日语系统上它将返回近似值Caffe Brilli.txt
,因为 932 代码页中缺少重音元音,然后用它们的“最佳匹配”替换" 非重音元音。根本无法翻译的字符被检索为?
(问号)。通常,在 Windows 下没有安全的方法来检测此类工件。
更多细节可在我对PHP 错误号的回复中找到。47096。
PHP 7.1 在 Windows 上支持 UTF-8 文件名,而不管 OEM 代码页。
问题是 Windows 使用 utf-16 作为文件系统字符串,而 Linux 和其他使用不同的字符集,但通常是 utf-8。您提供了一个 utf-8 字符串,但这在 Windows 中被解释为另一个 8 位字符集编码,可能是 Latin-1,然后在 utf-8 中用 2 个字节编码的非 ascii 字符被处理为如果它在 Windows 中是 2 个字符。
一个正常的解决方案是将源代码 100% 保存在 ascii 中,并在其他地方使用字符串。
使用com_dotnet
PHP 扩展,您可以访问 Windows' Scripting.FileSystemObject
,然后使用 UTF-8 文件/文件夹名称做任何您想做的事情。
我将其打包为 PHP 流包装器,因此非常易于使用:
首先验证com_dotnet
您的扩展是否已启用,php.ini
然后使用以下命令启用包装器:
stream_wrapper_register('win', 'Patchwork\Utf8\WinFsStreamWrapper');
最后,使用您习惯使用的函数(mkdir、fopen、rename 等),但在路径前加上win://
例如:
<?php
$dir_name = "Depósito";
mkdir('win://' . $dir_name );
?>
您可以使用此扩展程序来解决您的问题:https ://github.com/kenjiuno/php-wfio
$file = fopen("wfio://多国語.txt", "rb"); // in UTF-8
....
fclose($file);
我的一套工具可以在 Windows或linux上使用带有 UTF-8 的文件系统,PHP
并且与.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);
}
其他资源
从这个链接尝试 CodeIgniter Text helper 阅读关于 convert_accented_characters() 函数,它可以被定制
我不需要写太多,它很好用:
<?php
$dir_name = mb_convert_encoding("Depósito", "ISO-8859-1", "UTF-8");
mkdir($dir_name);
?>