1

我正在创建一个非常简单的文件搜索,其中搜索数据库是一个文本文件,每行一个文件名。该数据库是使用 PHP 构建的,并且通过 grepping 文件(也使用 PHP)找到匹配项。

这在 Linux 中效果很好,但在使用非 ascii 字符时不适用于 Mac。看起来名称在 HFS+ (MacOSX) 上的编码方式与在 ext3 (Linux) 上的编码方式不同。这是一个test.php:

<?php
$mystring = "abcóüÚdefå";
file_put_contents($mystring, "");
$h = dir('.');
$h->read(); // "."
$h->read(); // ".."
$filename = $h->read();

print "string: $mystring and filename: $filename are ";

if ($mystring == $filename) print "equal\n";
else print "different\n";

运行 MacOSX 时:

$ php test.php
string: abcóüÚdefå and filename: abcóüÚdefå are different
$ php test.php |cat -evt
string: abcóü?M-^Zdefå$ and filename: abco?M-^Au?M-^HU?M-^Adefa?M-^J are different$

在 Linux(或 MacOSX 上安装了 nfs 的 ext3 文件系统)上运行时:

$ php test.php
string: abcóüÚdefå and filename: abcóüÚdefå are equal
$ php test.php |cat -evt
string: abcM-CM-3M-CM-<M-CM-^ZdefM-CM-% and filename: abcM-CM-3M-CM-<M-CM-^ZdefM-CM-% are equal$

有没有办法让这个脚本在两个平台上返回“相等”?

4

3 回答 3

4

MacOSX 使用规范化形式 D (NFD) 来编码 UTF-8,而大多数其他系统使用 NFC

NFC 与 NFD

来自 unicode.org

NFD 到 NFC 的转换有多种 实现方式。在这里,我使用 PHP Normalizer 类来检测 NFD 字符串并将它们转换为 NFC。它在 PHP 5.3 中或通过PECL 国际化扩展可用。以下修改将使脚本工作:

...
$filename = $h->read();
if (!normalizer_is_normalized($filename)) {
   $filename = normalizer_normalize($filename);
}
...
于 2009-04-21T18:46:43.590 回答
3

似乎 Mac OS X/HFS+ 正在使用字符组合而不是单个字符。所以ó(U+00F3) 被编码为o(U+006F) + ´(U+CC81, COMBINING ACUTE ACCENT)。另请参阅Apple 的 Unicode 分解表

于 2009-04-21T17:38:29.633 回答
0

您是否检查过两个系统使用相同的语言环境?

PHP 脚本在两个系统上都使用什么编码?

我也会尝试使用strcmp而不是 equals 运算符。我不确定 equals 运算符是否在内部使用 strcmp ,但在您的情况下测试它是一件简单的事情。

于 2009-04-21T17:08:57.910 回答