Pregunta

Obtengo archivos de imágenes que tienen caracteres checos en el nombre (por ejemplo, ěščřžýáíé) y quiero cambiarles el nombre sin acentos para que sean más compatibles con la web.Pensé que podría usar una función str_replace simple pero no parece funcionar igual con la matriz de archivos que con una cadena literal.

Leo los archivos con readdir, después de comprobar la extensión.

function readFiles($dir, $ext = false) {
    if (is_dir($dir)) {
        if ($dh = opendir($dir)) {
            while (($file = readdir($dh)) !== false) {
                if($ext){  
                    if(end(explode('.', $file)) == $ext) {
                        $f[] = $file;
                    }
                } else {
                    $f[] = $file;
                }
            }

            closedir($dh);
            return $f;
        } else {
            return false;
        }
    } else {
        return false;
    }
}

$files = readFiles(".", "jpg");

$search = array('š','á','ž','í','ě','é','ř','ň','ý','č',' ');
$replace = array('s','a','z','i','e','e','r','n','y','c','-');

$string = "čšěáýísdjksnalci sášěééalskcnkkjy+ěéší";
$safe_string = str_replace($search, $replace, $string);

echo '<pre>';

foreach($files as $fl) {
    $safe_files[] = str_replace($search, $replace, $fl);
}

var_dump($files);
var_dump($safe_files);

var_dump($string);
var_dump($safe_string);

echo '</pre>';

Producción

array(6) {
  [0]=>
  string(21) "Hl�vka s listem01.jpg"
  [1]=>
  string(23) "Hl�vky v atelieru02.jpg"
  [2]=>
  string(17) "Jarn� v�hon03.jpg"
  [3]=>
  string(17) "Mlad� chmel04.jpg"
  [4]=>
  string(23) "Stavba chmelnice 05.jpg"
  [5]=>
  string(21) "Zimni chmelnice06.jpg"
}
array(6) {
  [0]=>
  string(21) "Hl�vka-s-listem01.jpg"
  [1]=>
  string(23) "Hl�vky-v-atelieru02.jpg"
  [2]=>
  string(17) "Jarn�-v�hon03.jpg"
  [3]=>
  string(17) "Mlad�-chmel04.jpg"
  [4]=>
  string(23) "Stavba-chmelnice-05.jpg"
  [5]=>
  string(21) "Zimni-chmelnice06.jpg"
}
string(53) "čšěáýísdjksnalci sášěééalskcnkkjy+ěéší"
string(38) "cseayisdjksnalci-saseeealskcnkkjy+eesi"

En este momento estoy usando WAMP, pero las respuestas que funcionan en todas las plataformas son aún mejores :)

¿Fue útil?

Solución

De acuerdo con las marcas 0xFFFD (que aparece en Firefox como diamantes con un signo de interrogación en el interior) que ya no está leyendo ellos utilizando la codificación correcta (lo que sería Unicode / UTF-8). En lo que encontré este fallo , parece estar relacionado.

Aquí hay otro SO tema sobre el que: php readdir con el idioma japonés el nombre del archivo

Al punto, espere hasta que se PHP6 estable y luego usarlo.

Sin relación con el problema: la Normalizador es una herramienta mejor para conseguir deshacerse de signos diacríticos .

Otros consejos

Si funciona con cuerdas pero no con matrices, solo se aplica en cadenas: -)

$search = array('š','á','ž','í','ě','é','ř','ň','ý','č',' ');
$replace = array('s','a','z','i','e','e','r','n','y','c','-');

len = count($safe_files)

for ($i=0; $i<len; $i++)
    $safe_files[$i] = str_replace($search, $replace, $safe_files[$i]);

str_replace aceptar matrices sólo para los 2 primeros params , y no el último. Puedo estar equivocado, pero de todos modos esto debería funcionar.

Si por cualquier medio, tiene un verdadero problema de codificación, sólo podría ser que usted OS utilizan un solo byte de codificación, mientras que el archivo de origen utilice otro, probablemente UTF-8.

En ese caso, hacer algo como:

$search = array('š','á','ž','í','ě','é','ř','ň','ý','č',' ');
$replace = array('s','a','z','i','e','e','r','n','y','c','-');

$code_encoding = "UTF-8"; // this is my guess, but put whatever is yours
$os_encoding = "CP-1250"; // this is my guess, but put whatever is yours

len = count($safe_files)

for ($i=0; $i<len; $i++)
{
    $safe_files[$i] = iconv($os_encoding , $code_encoding, $safe_files[$i]); // convert before replace
    /*
     ALternatively :
     $safe_files[$i] = mb_convert_encoding($safe_files[$i], $code_encoding , $os_encoding );
    */
    $safe_files[$i] = str_replace($search, $replace, $safe_files[$i]);
}

mb_convert_encoding () requerir la ext / extensión mbstring y iconv () requerir ext / iconv.

No directamente una respuesta a su pregunta, pero tal vez es posible que desee echar un vistazo a la función iconv() en PHP y más en particulare la opción //TRANSLIT que puede anexar al segundo argumento. Lo he utilizado varias veces girando cuerdas europa francés y oriental a sus a-z y homólogos url amigables.

De PHP.net ( http://www.php.net/ manual de / en / function.iconv.php )

  

Si añade la cadena // TRANSLIT a out_charset transliteración se activa. Esto significa que cuando un personaje no puede ser representado en el juego de caracteres de destino, se puede aproximar a través de uno o varios personajes que buscan de manera similar.

Su código fuente (y la cadena de prueba) parecen estar en UTF-8, mientras que los nombres de archivos parecen utilizar una codificación de un solo byte. Yo te sugeriría que se utiliza la misma codificación para su cadena de reemplazo. Para evitar problemas de codificación fuente, que será mejor para escribir caracteres acentuados en su código en una forma hexagonal (como \ XE8 para "c", etc.).

Así que lo hice funcionar en mi sistema Windows XP con esto

$search = array('š','á','ž','í','e','é','r','n','ý','c',' ');
$replace = array('s','a','z','i','e','e','r','n','y','c','-');

$files = readFiles(".", "jpg");
$len = count($files);

for($i = 0; $i < $len; $i++){
  if(mb_check_encoding($files[$i], 'ASCII')){
    $safe_files[$i] = $files[$i];
  }else{
    $safe_files[$i] = str_replace(
        $search, $replace, iconv("iso-8859-1", "utf-8//TRANSLIT", $files[$i]));
  }
  if($files[$i] != $safe_files[$i]){
    rename($files[$i], $safe_files[$i]);
  }
}

No sé si es casualidad o no, pero llamando mb_get_info() muestra

[internal_encoding] => ISO-8859-1

Aquí es otra función que encontré en la página strtr PHP

<?
// Windows-1250 to ASCII
// This function replace all Windows-1250 accent characters with
// thier non-accent ekvivalents. Useful for Czech and Slovak languages.

function win2ascii($str)    {   

$str = StrTr($str,
    "\xE1\xE8\xEF\xEC\xE9\xED\xF2",
    "\x61\x63\x64\x65\x65\x69\x6E");

$str = StrTr($str,
    "\xF3\xF8\x9A\x9D\xF9\xFA\xFD\x9E\xF4\xBC\xBE",
    "\x6F\x72\x73\x74\x75\x75\x79\x7A\x6F\x4C\x6C");

$str = StrTr($str,
    "\xC1\xC8\xCF\xCC\xC9\xCD\xC2\xD3\xD8",
    "\x41\x43\x44\x45\x45\x49\x4E\x4F\x52");

$str = StrTr($str,
    "\x8A\x8D\xDA\xDD\x8E\xD2\xD9\xEF\xCF",
    "\x53\x54\x55\x59\x5A\x4E\x55\x64\x44");

return $str;
}
?>

Básicamente, no fue un problema para convertir los caracteres europeos a un equivilent ASCII, pero no pude encontrar ninguna manera confiable de cambiar el nombre de los archivos (es decir, archivos de referencia con caracteres no ASCII).

Para UTF-8 uso la función PHP utf8_encode. Microsoft Windows utiliza la norma ISO-8859-1 por lo que en este caso es necesaria una conversión.

Ejemplo - una lista de los archivos en un directorio:

<?php
$dir_handle = opendir(".");
while (false !== ($file = readdir($dir_handle)))
{
  echo utf8_encode($file)."<br>";
}
?>

Area5one tiene razón -. Se trata de un problema de codificación diferente

Cuando he actualizado mi máquina de XP a Win7, también de actualizar mi versión de MySQL y PHP. En algún momento, los programas de PHP que utilizan para el trabajo dejó de funcionar. En particular, scandir, readdir y UTF-8 habían vivido felizmente juntos, pero ya no.

Por lo tanto, he modificado mi código. Las variables relacionadas con los datos tomados desde el final de disco duro en "_ISO" a reflecct codificación ISO-8859-1 de Windows, los datos de la base de datos MySQL va en las variables que terminan en '_utf'. Por lo tanto, el código de area5one lo desea:     $ Dir_handle_iso = opendir ( "");     mientras que (falso! == ($ file_iso = readdir ($ dir_handle_iso)))     {     $ File_utf = utf8_encode ($ archivo);     ...     }

Esto funciona para mí 100%:

setlocale(LC_ALL,"cs_CZ");
$new_str = iconv("UTF-8","ASCII//TRANSLIT",$orig_str);

file = $ mb_convert_encoding ($ archivo, 'UTF-8', "iso-8859-1"); Trabajado para mí (Windows, personajes daneses).

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top