Pergunta

Eu recebo arquivos de imagens que tenham checa caracteres no nome de ficheiro (por exemplo, ěščřžýáíé) e eu gostaria de mudar-lhes o nome sem os acentos, de modo que eles são mais compatíveis para a web.Eu pensei que eu poderia usar uma simples função str_replace mas ele parece não funcionar mesmo com o arquivo matriz como faz com um literal de cadeia de caracteres.

Eu li os arquivos com readdir, após a verificação de extensão.

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>';

Saída

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"

Agora eu estou correndo em WAMP, mas respostas que funcionam em plataformas são ainda melhores :)

Foi útil?

Solução

De acordo com o 0xFFFD marcas (que aparece no Firefox como diamantes com um ponto de interrogação dentro) você já não está a lê-los usando a codificação correta (o que seria Unicode / UTF-8).Como agora eu encontrei este erro, ele parece estar relacionado.

Aqui está outro MODO tópico sobre isso: php readdir problema com o idioma japonês de nome de arquivo

Para o ponto, espere até que eles se PHP6 estável e, em seguida, usá-lo.

Relacionado com o problema:o Normalizer é a melhor ferramenta para se livrar de sinais diacríticos.

Outras dicas

Se funcionar com strings, mas não com matrizes, apenas aplica-a em strings :-)

$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]);

Eu penso str_Replace Aceite matrizes apenas para os 2 primeiros parâmetros, e não o último. Posso estar errado, mas de qualquer maneira isso deve funcionar.

Se, por qualquer meio, você tem um problema de codificação real, pode ser apenas que você use uma codificação de byte única enquanto o arquivo de origem usa outro, provavelmente UTF-8.

Nesse caso, faça 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 () requer a extensão Ext/Mbstring e o iconv () requerem ext/iconv.

Não diretamente uma resposta para sua pergunta, talvez, mas você pode querer dar uma olhada no iconv() função em php e mais em particulare o //TRANSLIT opção que você pode anexar ao segundo argumento. Eu o usei várias vezes, transformando as cordas da Europa francesa e oriental para seus colegas AZ e URL.

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

Se você anexar a string // translit para a transliteração out_charset estiver ativada. Isso significa que, quando um personagem não pode ser representado no charset de destino, ele pode ser aproximado através de um ou vários caracteres de aparência semelhante.

Seu código-fonte (e a sequência de testes) parecem estar no UTF8, enquanto os nomes de arquivos parecem usar uma codificação de bytes. Eu sugiro que você use a mesma codificação para sua sequência de substituição. Para evitar problemas de codificação de origem, é melhor escrever chars acentuados em seu código em um formulário hexadecimal (como xe8 para "Č" etc).

Então eu consegui funcionar no meu sistema Windows XP por este

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

Não sei se é uma conincidência ou não, mas ligando mb_get_info() shows

[internal_encoding] => ISO-8859-1

Aqui está outra função que achei útil Na página PHP STRTR

<?
// 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;
}
?>

Basicamente, não era um problema converter os caracteres europeus em um ASCII equivocado, mas não encontrei uma maneira confiável de renomear os arquivos (ou seja, arquivos de referência com caracteres não-ASCII).

Para UTF-8, use a função PHP UTF8_ENCODE. O Microsoft Windows usa o ISO-8859-1, portanto, neste caso, é necessária uma conversão.

Exemplo - listando os arquivos em um diretor:

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

Area5one tem-direito - é um problema de codificação diferente.

Quando eu atualizei a minha máquina do XP para o Win7, eu também atualizou a minha versão do MySQL e PHP.Em algum lugar ao longo do caminho, programas PHP utilizado para trabalhar, parou de funcionar.Em particular, scandir, readdir e utf-8, viveram juntos e felizes, mas não mais.

Então, modifiquei o meu código.Variáveis relacionadas com os dados obtidos a partir do disco rígido final em "_iso" para reflecct Windows' ISO-8859-1 de codificação, os dados do banco de dados MySQL vai em variáveis terminando em "_utf".Assim, o código de area5one seria assim:$dir_handle_iso = opendir(".");while (false !== ($file_iso = readdir($dir_handle_iso))) { $file_utf = utf8_encode($arquivo);...}

Isso funciona para mim 100%:

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

$ file = mb_convert_encoding ($ file, 'utf-8', "iso-8859-1"); Trabalhou para mim (Windows, personagens dinamarqueses).

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