PHP中的UTF8文件名和不同的Unicode编码

时间:2009-07-07 01:37:27

标签: php unicode encoding utf-8 filepath

我在运行linux的服务器上有一个包含Unicode字符的文件。如果我SSH到服务器并使用tab-completion导航到包含unicode字符的文件/文件夹,我访问文件/文件夹没有问题。当我尝试通过PHP访问文件时出现问题(我从stat访问文件系统的函数)。如果我将PHP脚本生成的路径输出到浏览器并将其粘贴到终端中,该文件似乎也存在(即使查看终端文件路径完全相同)。

我将PHP设置为通过php_ini使用UTF8作为其默认编码,并设置mb_internal_encoding。我检查了PHP文件路径字符串编码,它应该是UTF8。稍微多了一点,我决定hexdump终端标签完成的é字符,并将其与PHP脚本创建的'常规'é字符的hexdump进行比较,或者手动输入键盘上的字符(OS x上的选项+ e + e)。结果如下:

echo -n é | hexdump
0000000 cc65 0081                              
0000003
echo -n é | hexdump
0000000 a9c3                                   
0000002

允许终端中正确文件引用的é字符是3字节的字符。我不知道从哪里开始,我应该在PHP中使用什么编码?我应该通过iconv还是mb_convert_encoding

将路径转换为其他编码

3 个答案:

答案 0 :(得分:5)

感谢两个答案中给出的提示,我能够找到一些方法来规范化给定字符的不同unicode分解。在我遇到的情况下,我正在访问由OS X Carbon应用程序创建的文件。它是一个相当流行的应用程序,因此它的文件名似乎遵循特定的unicode分解。

在PHP 5.3中引入了new set of functions,允许您将unicode字符串规范化为特定的分解。显然有四种分解标准可以将unicode字符串分解为。自版本2.3以来,Python已通过unicode.normalize获得了unicode规范化功能。关于python处理unicode字符串的This article有助于更好地理解编码/字符串处理。

以下是规范化unicode文件路径的快速示例:

filePath = unicodedata.normalize('NFD', filePath)

我发现NFD格式适用于我的所有目的,我想知道这是否是unicode文件名的标准分解。

答案 1 :(得分:3)

三字节序列实际上是e (0x65)的utf8表示,后跟combining ´ (0xcc 0x81),而0xc3 0xa9直接表示é
知道utf-8的归类应该知道可能的分解,但是我不知道如何在mac上启用它(并且可能重新编译php源代码)。 我能提供的最好的是"Using UTF-8 with Gentoo"描述。

答案 2 :(得分:1)

首先:你应该尽量避免对文件名强加语义。我无法确定为什么PHP会在您的方案中生成文件名,因此我无法建议您应该如何应用此规则。

é的不同(两个字节和三个字节)表示是Unicode中该字符的组合和分解变体的UTF-8编码。在Unicode中,这些是表示相同视觉角色的不同方式。 Unicode具有“规范化”的概念,其中相同字符的所有表示都被转换为单个表示,有点像将两个字符串压缩为小写以执行无标记比较。

Linux不会自动为文件名执行规范化或任何其他处理,因此文件可以用预先组合(如两个字节序列)或分解(如三个字节序列)字符或两者的任意组合命名,它是由谁命名的文件。如果要创建文件,可以设置策略(例如,始终使用预组合字符)并编写一些代码来强制执行。否则,你不能在这里依赖任何特定的规则。