Como faço para usar funções do sistema de arquivos em PHP, usando cordas UTF-8?

Não consigo usar o mkdir para criar pastas com caracteres UTF-8.

 

Mas, quando eu navegar nesta pasta no Windows Explorer, o nome da pasta se parece com isto:

 Depósito 

O que devo fazer?

Apenas urlencode a string desejada como um nome de arquivo. Todos os caracteres retornados de urlencode são válidos em nomes de arquivos (NTFS / HFS / UNIX), então você pode apenas urldecode os nomes dos arquivos de volta ao UTF-8 (ou qualquer codificação em que eles estavam).

Advertências (todas aplicam-se às soluções abaixo também):

  • Após url-codificação, o nome do arquivo deve ser inferior a 255 caracteres (provavelmente bytes).
  • UTF-8 tem várias representações para muitos caracteres (usando caracteres combinados). Se você não normalizar seu UTF-8, você pode ter problemas para pesquisar com glob ou reabrir um arquivo individual.
  • Você não pode confiar em funções scandir ou similares para classificar alfa. Você deve urldecode os nomes dos arquivos e usar um algoritmo de sorting com conhecimento de UTF-8 (e colações).

Soluções precárias

As seguintes são soluções menos atractivas, mais complicadas e com mais ressalvas.

No Windows, o wrapper do sistema de arquivos PHP espera e retorna as seqüências ISO-8859-1 para nomes de arquivos / diretórios. Isso dá duas opções:

  1. Use UTF-8 livremente em seus nomes de arquivos, mas entenda que caracteres não-ASCII aparecerão incorretos fora do PHP. Um caractere não-ASCII UTF-8 será armazenado como vários caracteres ISO-8859-1 únicos . Por exemplo, aparecerá como ó no Windows Explorer.

  2. Limite os nomes dos arquivos / diretórios aos caracteres representáveis ​​no ISO-8859-1 . Na prática, você passará as suas cadeias UTF-8 através do formato utf8_decode antes de usá-las nas funções do sistema de arquivos e passar as inputs scandir dá-lhe através de utf8_encode para obter os nomes de arquivos originais no UTF-8.

As advertências são abundantes!

  • Se algum byte passado para uma function do sistema de arquivos corresponder a um caractere do sistema de arquivos do Windows inválido no ISO-8859-1, você não tem sorte.
  • O Windows pode usar uma codificação diferente de ISO-8859-1 em locais não ingleses. Eu acho que geralmente será um ISO-8859- #, mas isso significa que você precisará usar mb_convert_encoding vez de utf8_decode .

Este pesadelo é por que você provavelmente deveria simplesmente transliterar para criar nomes de arquivos.

Sob Unix e Linux (e, possivelmente, no OS X também), a codificação do sistema de arquivos atual é dada pelo parâmetro de localidade LC_CTYPE (veja a function setlocale() ). Por exemplo, pode avaliar algo como en_US.UTF-8 que significa que a codificação é UTF-8. Em seguida, os nomes dos arquivos e seus caminhos podem ser criados com fopen() ou recuperados por dir() com essa codificação.

No Windows, o PHP funciona como um “programa não compatível com Unicode”, então os nomes de arquivos são convertidos de um lado para o outro do UTF-16 usado pelo sistema de arquivos (Windows 2000 e posterior) para a “página de código” selecionada. O painel de controle “Opções regionais e de idioma”, painel de tabulação “Formatos” define a página de código recuperada pela opção LC_CTYPE , enquanto o “Administrativo -> Idioma para programas não-Unicode” define a página de códigos de tradução para nomes de arquivos. Nos países ocidentais, o parâmetro LC_CTYPE avalia algo como language_country.1252 que 1252 é a página de códigos, também conhecida como “codificação do Windows-1252”, que é similar (mas não exatamente igual) ao ISO-8859-1. No Japão, a página de códigos 932 é geralmente configurada, e assim por diante para outros países. Em PHP, você pode criar arquivos cujo nome pode ser expresso com a página de código atual. Vice-versa, nomes de arquivos e caminhos recuperados do sistema de arquivos são convertidos de UTF-16 para bytes usando a página de código atual “melhor-ajuste” .

Esse mapeamento é aproximado, então alguns personagens podem ser manchados de forma imprevisível. Por exemplo, Caffé Brillì.txt seria retornado por dir() como a seqüência de PHP Caff\xE9 Brill\xEC.txt conforme esperado se a página de código atual for 1252, enquanto retornaria o Caffe Brilli.txt aproximado em um sistema japonês porque as vogais acentuadas estão faltando na página de códigos 932 e depois são substituídas por suas vogais não acentuadas “melhor ajustadas”. Caracteres que não podem ser traduzidos de forma alguma são recuperados como ? (ponto de interrogação). Em geral, no Windows não há nenhuma maneira segura de detectar tais artefatos.

Mais detalhes estão disponíveis na minha resposta ao bug do PHP no. 47096 .

O problema é que o Windows usa o utf-16 para as seqüências do sistema de arquivos, enquanto o Linux e outros usam diferentes conjuntos de caracteres, mas geralmente utf-8. Você forneceu uma string utf-8, mas isso é interpretado como outra codificação de conjunto de caracteres de 8 bits no Windows, talvez latino-1 e, em seguida, o caracter não-ascii, codificado com 2 bytes no utf-8, é tratado como se fosse 2 caracteres no Windows.

Uma solução normal é manter seu código fonte 100% em ascii, e ter cordas em outro lugar.

O PHP 7.1 suporta nomes de arquivos UTF-8 no Windows desconsiderando a página de códigos OEM.

Obrigado.

Usando a extensão PHP com_dotnet , você pode acessar o Windows ‘ Scripting.FileSystemObject e, em seguida, faça tudo o que quiser com nomes de arquivos / pastas UTF-8.

Eu empacotei isso como um wrapper de stream PHP, por isso é muito fácil de usar:

https://github.com/nicolas-grekas/Patchwork-UTF8/blob/lab-windows-fs/class/Patchwork/Utf8/WinFsStreamWrapper.php

Primeiro, verifique se a extensão com_dotnet está ativada no seu php.ini seguida, habilite o wrapper com:

 stream_wrapper_register('win', 'Patchwork\Utf8\WinFsStreamWrapper'); 

Finalmente, use as funções que você usou (mkdir, fopen, renomear, etc.), mas prefira seu caminho com win://

Por exemplo:

  

Você poderia usar essa extensão para resolver seu problema: https://github.com/kenjiuno/php-wfio

 $file = fopen("wfio://多国語.txt", "rb"); // in UTF-8 .... fclose($file); 

Experimente CodeIgniter Text helper a partir deste link Leia sobre a function convert_accented_characters (), pode ser costumizada

O meu conjunto de ferramentas para usar o sistema de arquivos com UTF-8 no Windows OR linux via PHP e compatível com o arquivo de verificação .htaccess existe:

 function define_cur_os(){ //$cur_os=strtolower(php_uname()); $cur_os=strtolower(PHP_OS); if(substr($cur_os, 0, 3) === 'win'){ $cur_os='windows'; } define('CUR_OS',$cur_os); } function filesystem_encode($file_name=''){ $file_name=urldecode($file_name); if(CUR_OS=='windows'){ $file_name=iconv("UTF-8", "ISO-8859-1//TRANSLIT", $file_name); } return $file_name; } function custom_mkdir($dir_path='', $chmod=0755){ $dir_path=filesystem_encode($dir_path); if(!is_dir($dir_path)){ if(!mkdir($dir_path, $chmod, true)){ //handle mkdir error } } return $dir_path; } function custom_fopen($dir_path='', $file_name='', $mode='w'){ if($dir_path!='' && $file_name!=''){ $dir_path=custom_mkdir($dir_path); $file_name=filesystem_encode($file_name); return fopen($dir_path.$file_name, $mode); } return false; } function custom_file_exists($file_path=''){ $file_path=filesystem_encode($file_path); return file_exists($file_path); } function custom_file_get_contents($file_path=''){ $file_path=filesystem_encode($file_path); return file_get_contents($file_path); } 

Recursos adicionais

Intereting Posts