在 PHP 中,如何处理 HFS 上编码文件名的差异? 与其他地方相比?
我正在创建一个非常简单的文件搜索,其中搜索数据库是一个文本文件,每行一个文件名。 数据库是使用 PHP 构建的,并通过 grep 文件(也使用 PHP)找到匹配项。
这在 Linux 中效果很好,但 不适用于 Mac使用非 ASCII 字符。 看起来 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$
有没有办法让这个脚本在两个平台上返回“相等”?
I am creating a very simple file search, where the search database is a text file with one file name per line. The database is built with PHP, and matches are found by grepping the file (also with PHP).
This works great in Linux, but not on Mac when non-ascii characters are used. It looks like names are encoded differently on HFS+ (MacOSX) than on e.g. ext3 (Linux). Here's a 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";
When run 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$
When run on Linux (or on a nfs-mounted ext3 filesystem on MacOSX):
$ 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$
Is there a way to make this script return "equal" on both platforms?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
MacOSX 使用规范化形式 D (NFD) 来编码 UTF-8,而大多数其他系统使用NFC。
(来自 unicode.org)
有 几个 NFD 到 NFC 转换的实现。 在这里,我使用 PHP Normalizer 类 来检测 NFD 字符串并转换它们至 NFC。 它可以在 PHP 5.3 中使用,也可以通过 PECL 国际化扩展使用。 以下修改将使脚本正常工作:
MacOSX uses normalization form D (NFD) to encode UTF-8, while most other systems use NFC.
(from unicode.org)
There are several implementations on NFD to NFC conversion. Here I've used the PHP Normalizer class to detect NFD strings and convert them to NFC. It's available in PHP 5.3 or through the PECL Internationalization extension. The following amendment will make the script work:
Mac OS X/HFS+ 似乎使用字符组合而不是单个字符。 因此,
ó
(U+00F3) 被编码为o
(U+006F) +´
(U+CC81,组合尖锐重音) 。 另请参阅 Apple 的 Unicode 分解表。It seems that Mac OS X/HFS+ is using character combinations instead of single characters. So the
ó
(U+00F3) is instead encoded aso
(U+006F) +´
(U+CC81, COMBINING ACUTE ACCENT). See also Apple’s Unicode Decomposition Table.您是否检查过两个系统使用相同的区域设置?
PHP 脚本在两个系统上使用什么编码?
我还会尝试使用 strcmp 而不是 equals 运算符。 我不确定 equals 运算符是否在内部使用 strcmp,但在您的情况下进行测试很简单。
Have you checked that both systems use the same locale?
What encoding is the PHP script using on both systems?
I would also try using strcmp instead of the equals operator. I'm not sure if the equals operator uses strcmp internally, but it's a simple thing to test out in your case.