Em PHP, como faço para lidar com a diferença de nomes de arquivos codificados em HFS + vs. outro lugar?

StackOverflow https://stackoverflow.com/questions/773574

Pergunta

Estou criando uma pesquisa de arquivo muito simples, onde o banco de dados de pesquisa é um arquivo de texto com um nome de arquivo por linha. O banco de dados é construído com PHP e partidas são encontrados por grepping o arquivo (também com PHP).

Isso funciona muito bem em Linux, mas não no Mac quando não-ascii caracteres são usados ??. Parece que os nomes são codificados de forma diferente em HFS + (MacOSX) do que no exemplo ext3 (Linux). Aqui está um 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";

Ao executar 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$

Quando executado no Linux (ou em um NFS montado sistema de arquivos ext3 em 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$

Existe uma maneira de fazer este retorno script "igual" em ambas as plataformas?

Foi útil?

Solução

MacOSX usa forma normalização D (DFN) para codificar UTF-8, enquanto mais outros sistemas usam NFC .

NFC vs NFD

( de unicode.org )

vários implementações em NFD à conversão NFC. Aqui eu usei o PHP Normalizer classe para detectar cordas NFD e convertê-los para NFC. Ele está disponível no PHP 5.3 ou através do PECL Internacionalização extensão . A seguinte alteração fará com que o trabalho de script:

...
$filename = $h->read();
if (!normalizer_is_normalized($filename)) {
   $filename = normalizer_normalize($filename);
}
...

Outras dicas

It seems that Mac OS X/HFS+ is using character combinations instead of single characters. So the ó (U+00F3) is instead encoded as o (U+006F) + ´ (U+CC81, COMBINING ACUTE ACCENT). See also Apple’s Unicode Decomposition Table.

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.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top