Come posso utilizzare le funzioni del filesystem in PHP, usando stringhe UTF-8?
-
20-09-2019 - |
Domanda
Non posso usare mkdir
Per creare cartelle con caratteri UTF-8:
<?php
$dir_name = "Depósito";
mkdir($dir_name);
?>
Quando navigo questa cartella in Windows Explorer, il nome della cartella sembra così:
Depósito
Cosa dovrei fare?
Sto usando PHP5
Soluzione
Solo urlencode
La stringa desiderata come nome file. Tutto personaggi restituiti da urlencode
sono validi nei file di file (NTFS/HFS/UNIX), quindi puoi solo urldecode
I nomi dei file di nuovo su UTF-8 (o qualunque codifica in cui si trovassero).
Avvertenze (tutti si applicano anche alle soluzioni seguenti):
- Dopo la codifica dell'URL, il nome file deve essere inferiore a 255 caratteri (probabilmente byte).
- UTF-8 ha rappresentazioni multiple per molti personaggi (usando i personaggi combinanti). Se non normalizzi il tuo UTF-8, potresti avere difficoltà a cercare
glob
o riapertura di un singolo file. - Non puoi fare affidamento
scandir
o funzioni simili per la disorzione alfa. Deviurldecode
I nomi di file utilizzano quindi un algoritmo di ordinamento a conoscenza di UTF-8 (e COLLAZIONI).
Soluzioni peggiori
Quelle che segue sono soluzioni meno interessanti, più complicate e con più avvertenze.
Su Windows, il wrapper del filesystem PHP si aspetta e restituisce stringhe ISO-8859-1 per i nomi di file/directory. Questo ti dà due scelte:
Usa l'UTF-8 liberamente nei tuoi file di file, ma capisci che i personaggi non ASCII lo faranno sembrano errato fuori Php. Un char UTF-8 non ASCII verrà archiviato come multiplo separare Personaggi ISO-8859-1. Per esempio
ó
verrà visualizzato comeó
In Windows Explorer.Limita i nomi del file/directory a personaggi rappresentabili in ISO-8859-1. In pratica, passerai le tue stringhe UTF-8
utf8_decode
Prima di usarli nelle funzioni del filesystem e passare le vociscandir
ti dà attraversoutf8_encode
Per ottenere i file di file originale in UTF-8.
Avvertimenti a bizzeffe!
- Se non ci sono byte Passato a una funzione del filesystem corrisponde a Carattere di filesystem di Windows non valido In ISO-8859-1, sei sfortunato.
- finestre Maggio Utilizzare una codifica diversa da ISO-8859-1 in locali non inglesi. Immagino che di solito sarà uno di ISO-8859-#, ma questo significa che dovrai usare
mb_convert_encoding
invece diutf8_decode
.
Questo incubo è il motivo per cui probabilmente dovresti solo traslitterare Per creare filenature.
Altri suggerimenti
Sotto UNIX e Linux (e possibilmente anche in OS X), la codifica del file system corrente è data dal LC_CTYPE
parametro locale (vedi funzione setlocale()
). Ad esempio, può valutare qualcosa di simile en_US.UTF-8
Ciò significa che la codifica è UTF-8. Quindi i nomi dei file e i loro percorsi possono essere creati fopen()
o recuperato da dir()
con questa codifica.
In Windows, PHP opera come un "programma non consapevole non unicode", quindi i nomi dei file vengono convertiti avanti e indietro dall'UTF-16 utilizzato dal file system (Windows 2000 e successivamente) nella "pagina del codice" selezionata. Il pannello di controllo "Opzioni regionali e linguistiche", formati di scheda "" imposta la pagina del codice recuperata dal LC_CTYPE
Opzione, mentre "Amministrativo -> Lingua per programmi non UNICODE" imposta la pagina Codice di traduzione per i nomi dei file. Nei paesi occidentali il LC_CTYPE
Il parametro valuta qualcosa di simile language_country.1252
dove 1252 è la pagina del codice, nota anche come "codifica Windows-1252" che è simile (ma non esattamente uguale) a ISO-8859-1. In Giappone la pagina del codice 932 è di solito impostata invece, e così via per altri paesi. In PHP è possibile creare file il cui nome può essere espresso con la pagina del codice corrente. Viceversa, nomi di file e percorsi recuperati dal file system vengono convertiti da UTF-16 in byte usando il Pagina del codice corrente "best-fit".
Questa mappatura è approssimata, quindi alcuni personaggi potrebbero essere mangrati in modo imprevedibile. Per esempio, Caffé Brillì.txt
verrebbe restituito da dir()
Come stringa PHP Caff\xE9 Brill\xEC.txt
Come previsto se la pagina del codice corrente è 1252, mentre restituirebbe l'approssimazione Caffe Brilli.txt
Su un sistema giapponese perché mancano vocali accentati dalla pagina del codice 932 e quindi sostituite con le vocali non accentate "più adatte". I personaggi che non possono essere tradotti sono affatto recuperati come ?
(punto interrogativo). In generale, sotto Windows non esiste un modo sicuro per rilevare tali artefatti.
Maggiori dettagli sono disponibili nella mia risposta al Bug php n. 47096.
PHP 7.1 supporta i fileNamme UTF-8 su Windows che ignora il codepage OEM.
Il problema è che Windows utilizza UTF-16 per stringhe del filesystem, mentre Linux e altri utilizzano diversi set di caratteri, ma spesso UTF-8. Hai fornito una stringa UTF-8, ma questo è interpretato come un altro set di caratteri a 8 bit che codifica in Windows, forse Latin-1, e quindi il carattere non ASCII, che è codificato con 2 byte in UTF-8, viene gestito come Se erano 2 caratteri in Windows.
Una soluzione normale è mantenere il codice sorgente al 100% in ASCII e avere stringhe da qualche altra parte.
Usando il com_dotnet
Estensione PHP, puoi accedere a Windows ' Scripting.FileSystemObject
, quindi fai tutto ciò che desideri con i nomi di file/cartelle UTF-8.
L'ho confezionato come un involucro di flusso PHP, quindi è molto facile da usare:
Prima verifica che il com_dotnet
L'estensione è abilitata nel tuo php.ini
Quindi abilita l'involucro con:
stream_wrapper_register('win', 'Patchwork\Utf8\WinFsStreamWrapper');
Infine, usa le funzioni per cui sei abituato (mkdir, fopen, rinominare, ecc.), Ma prefigurare il tuo percorso con win://
Per esempio:
<?php
$dir_name = "Depósito";
mkdir('win://' . $dir_name );
?>
Potresti usare questa estensione per risolvere il tuo problema: https://github.com/kenjiuno/php-wfio
$file = fopen("wfio://多国語.txt", "rb"); // in UTF-8
....
fclose($file);
Prova un supporto di testo codeigniter da questo linkLeggi sulla funzione convert_accented_characters (), può essere costumita
Il mio set di strumenti per utilizzare il filesystem con UTF-8 su Windows O Linux via PHP
e compatibile con .htaccess
Controllare il file esiste:
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);
}
Risorse addizionali
Non ho bisogno di scrivere molto, funziona bene:
<?php
$dir_name = mb_convert_encoding("Depósito", "ISO-8859-1", "UTF-8");
mkdir($dir_name);
?>