В PHP, как мне справиться с разницей в закодированных именах файлов в HFS + и в других местах? - PullRequest
1 голос
/ 21 апреля 2009

Я создаю очень простой поиск файлов, где база данных поиска представляет собой текстовый файл с одним именем файла в строке. База данных построена с использованием 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 (или в монтированной nfs файловой системе ext3 в 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$

Есть ли способ заставить этот скрипт возвращать "равные" на обеих платформах?

Ответы [ 3 ]

4 голосов
/ 21 апреля 2009

MacOSX использует форму нормализации D (NFD) для кодирования UTF-8, в то время как большинство других систем используют NFC .

NFC vs NFD

( от unicode.org )

Существует несколько реализаций по преобразованию NFD в NFC. Здесь я использовал класс PHP Normalizer, чтобы обнаружить строки NFD и преобразовать их в NFC. Он доступен в PHP 5.3 или через расширение PECL Internationalization . Следующая поправка заставит скрипт работать:

...
$filename = $h->read();
if (!normalizer_is_normalized($filename)) {
   $filename = normalizer_normalize($filename);
}
...
3 голосов
/ 21 апреля 2009

Кажется, что Mac OS X / HFS + использует комбинации символов вместо отдельных символов. Таким образом, ó (U + 00F3) вместо этого кодируется как o (U + 006F) + ´ (U + CC81, ACBE ACCENT ACCENT). См. Также Таблица разложения Unicode от Apple .

0 голосов
/ 21 апреля 2009

Вы проверили, что обе системы используют один и тот же язык?

Какую кодировку использует скрипт PHP в обеих системах?

Я бы также попытался использовать strcmp вместо оператора равенства. Я не уверен, что оператор equals использует strcmp для внутреннего использования, но это просто проверить в вашем случае.

...