2010-12-15 78 views
24

Lors de l'utilisation de la fonction pathinfo() de PHP sur un nom de fichier connu pour être UTF-8, il ne renvoie pas la valeur correcte, sauf si des caractères 'normaux' devant le personnage spécial.Faire PHP pathinfo() retourner le nom de fichier correct si le nom de fichier est UTF-8

Exemples:
pathinfo('aä.pdf') retourne:

Array 
(
[dirname] => [the dir] 
[basename] => aä.pdf 
[extension] => pdf 
[filename] => aä 
) 

ce qui est bien et dandy, mais pathinfo('äa.pdf') retourne:

Array 
(
[dirname] => [the dir] 
[basename] => a.pdf 
[extension] => pdf 
[filename] => a 
) 

Ce qui est pas tout à fait ce que j'attendais. Pire encore, pathinfo('ä.pdf') retours:

Array 
(
[dirname] => [the dir] 
[basename] => .pdf 
[extension] => pdf 
[filename] => 
) 

Pourquoi fait-il cela? Cela vaut pour tous les caractères accentués que j'ai testés.

+3

La plupart des fonctions PHP de base ne traitent pas de jeux de caractères autres que ISO-8859-1 (Latin-1). Vous êtes seulement une option réelle est de ré-implémenter la fonction vous-même en utilisant des fonctions sécurisées multi-byte charset (fonctions 'mb_string') – ircmaxell

+1

quelle version de PHP exécutez-vous? – ajreal

+0

@ajreal c'est PHP 5.2.6-1 + lenny9 sur debian lenny – Zsub

Répondre

7

Un travail autour temporaire pour ce problème semble être pour vous assurer qu'il est un caractère « normal » devant les caractères accentués, comme ceci:

function getFilename($path) 
{ 
    // if there's no '/', we're probably dealing with just a filename 
    // so just put an 'a' in front of it 
    if (strpos($path, '/') === false) 
    { 
     $path_parts = pathinfo('a'.$path); 
    } 
    else 
    { 
     $path= str_replace('/', '/a', $path); 
     $path_parts = pathinfo($path); 
    } 
    return substr($path_parts["filename"],1); 
} 

Notez que nous remplaçons toutes les occurrences de '/'avec'/a 'mais c'est correct, puisque nous retournons à partir du décalage 1 du résultat. Fait intéressant, la partie dirname de pathinfo() semble fonctionner, donc aucune solution de contournement n'est nécessaire.

+2

Ceci est toujours un bug en 2016, mais 'setlocale (LC_ALL, 'en_US.UTF-8');' fonctionne. – Drakes

5
+0

http://php.net/ChangeLog-5.php – ajreal

+0

Ce bug concerne les caractères non-ascii, pas les caractères UTF-8. Donc je ne sais pas si c'est 100% applicable (ça peut être, donc non -1, mais c'est aussi un très vieux bug, donc je suis à peu près sûr que ce n'est pas la cause) ... – ircmaxell

+0

@ircmaxell Mes personnages en effet sont (ou à tout le moins devraient être) UTF-8. C'est-à-dire: mon locale est UTF-8 et le fichier .php est sauvegardé en UTF-8. Je pense que je vais réécrire la fonction en utilisant pathinfo() pour utiliser ma propre logique, mais c'est un peu "meh". – Zsub

9

J'ai utilisé ces fonctions dans PHP 5.3.3 - 5.3.18 pour gérer le problème UTF-8 dans basename() et pathinfo().

 

if (!function_exists("mb_basename")) 
{ 
    function mb_basename($path) 
    { 
    $separator = " qq "; 
    $path = preg_replace("/[^ ]/u", $separator."\$0".$separator, $path); 
    $base = basename($path); 
    $base = str_replace($separator, "", $base); 
    return $base; 
    } 
} 
 
if (!function_exists("mb_pathinfo")) 
{ 
    function mb_pathinfo($path, $opt = "") 
    { 
    $separator = " qq "; 
    $path = preg_replace("/[^ ]/u", $separator."\$0".$separator, $path); 
    if ($opt == "") $pathinfo = pathinfo($path); 
    else $pathinfo = pathinfo($path, $opt); 

    if (is_array($pathinfo)) 
    { 
     $pathinfo2 = $pathinfo; 
     foreach($pathinfo2 as $key => $val) 
     { 
     $pathinfo[$key] = str_replace($separator, "", $val); 
     } 
    } 
    else if (is_string($pathinfo)) $pathinfo = str_replace($separator, "", $pathinfo); 
    return $pathinfo; 
    } 
} 
1

Lorsque les caractères ansi de processus, la fonction pathinfo faire correctement.

Sur la base de cette note, nous allons convertir (encoder) l'entrée en chariots ansi, puis utiliser encore la fonction pathinfo pour conserver tout son contenu. Enfin, nous allons convertir (décoder) les valeurs de sortie au format original.

Et démo comme mugissement.

function _pathinfo($path, $options = null) 
{ 
    $path = urlencode($path); 
    $parts = null === $options ? pathinfo($path) : pathinfo($path, $options); 
    foreach ($parts as $field => $value) { 
     $parts[$field] = urldecode($value); 
    } 
    return $parts; 
} 
// calling 
_pathinfo('すtest.jpg'); 
_pathinfo('すtest.jpg', PATHINFO_EXTENSION); 
6

avant utilisation PathInfo

setlocale(LC_ALL,'en_US.UTF-8'); 
pathinfo($OriginalName, PATHINFO_FILENAME); 
pathinfo($OriginalName, PATHINFO_BASENAME); 
+2

La réponse peut devenir plus précieuse si vous ajoutez des explications et des liens vers la documentation, de sorte que le poster original et les autres utilisateurs peuvent en tirer des leçons. –

+0

Cette réponse a aidé et c'est simple. S'il vous plaît ajouter plus d'explications pour améliorer sa valeur pour les autres. – Drakes

+0

Là dans une explication: https://stackoverflow.com/questions/45268499/php-basename-and-pathinfo-with-multibytes-utf-8-file-names/45268539#45268539 –

0
private function _pathinfo($path, $options = null) { 
    $result = pathinfo(' ' . $path, $options); 
    return substr($result, 1); 
}