2010-12-15 14 views
24

Al usar la función pathinfo() de PHP en un nombre de archivo UTF-8, no devuelve el valor correcto, a menos que haya caracteres 'normales' en frente al personaje especial.Hacer que PHP pathinfo() devuelva el nombre de archivo correcto si el nombre del archivo es UTF-8

Ejemplos:
pathinfo('aä.pdf') devuelve:

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

que es fino y elegante, pero pathinfo('äa.pdf') devuelve:

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

que no es exactamente lo que yo esperaba. Peor aún, pathinfo('ä.pdf') devuelve:

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

¿Por qué hace esto? Esto va para todos los personajes acentuados que he probado.

+3

mayoría de las funciones básicas de PHP no se ocupan de juegos de caracteres que no sean ISO-8859-1 (Latin-1). La única opción real es volver a implementar la función usted mismo utilizando funciones seguras de chaster de múltiples bytes (funciones 'mb_string') – ircmaxell

+1

¿Qué versión de PHP está ejecutando? – ajreal

+0

@ajreal es PHP 5.2.6-1 + lenny9 en debian lenny – Zsub

Respuesta

7

Una solución alternativa temporal para este problema parece ser la de asegurarse de que hay un carácter 'normal' frente a los caracteres acentuados, así:

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); 
} 

Tenga en cuenta que se reemplaza todas las ocurrencias de '/'con'/a ', pero está bien, ya que volvemos a partir del desplazamiento 1 del resultado. Curiosamente, la parte dirname de pathinfo() parece funcionar, por lo que no se necesita ninguna solución.

+2

Esto sigue siendo un error en 2016, pero 'setlocale (LC_ALL, 'en_US.UTF-8');' funciona. – Drakes

5
+0

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

+0

Ese error está relacionado con caracteres no ascii, no con caracteres UTF-8. Así que no estoy seguro si es 100% aplicable (puede ser, entonces no -1, pero también es un error muy antiguo, así que estoy bastante seguro de que no es la causa raíz) ... – ircmaxell

+0

@ircmaxell Mis personajes de hecho son (o al menos deberían ser) UTF-8. Es decir: mi configuración regional es UTF-8 y el archivo .php se guarda como UTF-8. Creo que reescribiré la función usando pathinfo() para usar mi propia lógica, pero es como 'meh'. – Zsub

9

He utilizado estas funciones en PHP 5.3.3 - 5.3.18 para manejar el problema UTF-8 en basename() y 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

Cuando caracteres ANSI proceso, la función pathinfo hacen correctamente.

Base esta nota, convertiremos la entrada (codificación) a los caracteres ansi y seguiremos usando la función pathinfo para mantener todo.

Finalmente, convertiremos (descodificando) los valores de salida al formato original.

Y demo como bramido.

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

antes de su uso Pathinfo

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

La respuesta puede ser más valiosa si agrega algunas explicaciones y enlaces a la documentación, para que el póster original y otros usuarios puedan aprender de ella. –

+0

Esta respuesta ayudó y es simple. Agregue más explicaciones para mejorar su valor para los demás. – Drakes

+0

Hay una explicación: 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); 
} 
Cuestiones relacionadas