En PHP, comment puis-je faire face à la différence dans les noms de fichiers codés sur HFS + vs ailleurs?

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

Question

Je suis en train de créer une recherche de fichiers très simple, où la base de données de recherche est un fichier texte avec un nom de fichier par ligne. La base de données est construite avec PHP, et les matches sont trouvés par grepper le fichier (également avec PHP).

Cela fonctionne très bien sous Linux, mais pas sur Mac en cas de non-ascii caractères sont utilisés . On dirait que les noms sont codés différemment sur HFS + (MacOSX) que sur par exemple ext3 (Linux). Voici un 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";

Lors de l'exécution 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$

Lorsqu'il est exécuté sur Linux (ou sur un système de fichiers ext3 nfs-montés sur 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$

Y at-il un moyen de faire ce retour de script « égal » sur les deux plates-formes?

Était-ce utile?

La solution

MacOSX utilise sous forme de normalisation D (DNF) pour coder UTF-8, tandis que plus d'autres systèmes utilisent NFC.

NFC vs NFD

( de unicode.org )

Il y a plusieurs implémentations sur DNF à la conversion NFC. Ici, je l'ai utilisé la classe PHP Normalizer pour détecter les chaînes NFD et de les convertir NFC. Il est disponible en PHP 5.3 ou par le PECL l'extension Internationalisation . L'amendement suivant fera le travail de script:

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

Autres conseils

Il semble que Mac OS X / HFS + utilise des combinaisons de caractères au lieu de caractères simples. Ainsi, le ó (U + 00F3) est codé en tant que place o (U + 006F) + ´ (U + CC81, COMBINER AIGUË APPOINT). Voir aussi Tableau Décomposition Unicode d'Apple .

Avez-vous vérifié que les deux systèmes utilisent les mêmes paramètres régionaux?

Qu'est-ce que l'encodage est le script PHP en utilisant sur les deux systèmes?

Je également essayer d'utiliser strcmp au lieu de l'opérateur égal. Je ne sais pas si l'opérateur equals utilise strcmp en interne, mais il est une chose simple à tester dans votre cas.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top