Je ne peux pas utiliser mkdir
pour créer des dossiers avec des caractères UTF-8:
<?php
$dir_name = "Depósito";
mkdir($dir_name);
?>
lorsque je navigue dans ce dossier dans l'Explorateur Windows, le nom du dossier se présente comme suit:
Depósito
Que devrais-je faire?
J'utilise php5
Just urlencode
la chaîne souhaitée en tant que nom de fichier.Tous les caractères renvoyés par urlencode
sont valides dans les noms de fichiers (NTFS/HFS/UNIX), vous pouvez donc simplement urldecode
les noms de fichiers revenir à UTF-8 (ou le codage dans lequel ils étaient).
Mises en garde (toutes s'appliquent également aux solutions ci-dessous):
glob
ou à rouvrir un fichier individuel.scandir
ou des fonctions similaires pour le tri alpha. Vous devez urldecode
les noms de fichiers, puis utiliser un algorithme de tri prenant en compte UTF-8 (et des classements).Les solutions suivantes sont moins attrayantes, plus compliquées et avec plus de mises en garde.
Sous Windows, l’enveloppe de système de fichiers PHP attend et renvoie les chaînes ISO-8859-1 pour les noms de fichier/répertoire. Cela vous donne deux choix:
Utilisez librement UTF-8 dans vos noms de fichiers, mais comprenez que les caractères non-ASCII apparaîtront inexact en dehors de PHP. Un caractère UTF-8 non-ASCII sera stocké sous forme de plusieurs un seul ISO-8859-1 caractères. Par exemple. ó
apparaîtra en tant que ó
dans l'Explorateur Windows.
Limitez les noms de fichiers/répertoires à caractères pouvant être représentés dans ISO-8859-1 . En pratique, vous passerez vos chaînes UTF-8 par le biais de utf8_decode
avant de les utiliser dans des fonctions de système de fichiers, puis vous ferez passer les entrées scandir
par utf8_encode
pour obtenir les noms de fichier d'origine en UTF-8.
Mises en garde à gogo!
mb_convert_encoding
au lieu de utf8_decode
.Ce cauchemar est la raison pour laquelle vous devriez probablement juste translittérer _ créer des noms de fichiers.
Sous Unix et Linux (et éventuellement sous OS X également), le codage actuel du système de fichiers est donné par le paramètre régional LC_CTYPE
(voir la fonction setlocale()
). Par exemple, il se peut que quelque chose comme en_US.UTF-8
indique que le codage est UTF-8. Ensuite, les noms de fichiers et leurs chemins peuvent être créés avec fopen()
ou récupérés par dir()
avec cet encodage.
Sous Windows, PHP fonctionne comme un "programme non compatible avec Unicode", puis les noms de fichier sont convertis en aller et retour de l'UTF-16 utilisé par le système de fichiers (Windows 2000 et versions ultérieures) en "page de code" sélectionnée. . Le panneau de configuration "Options régionales et linguistiques", panneau d'onglets "Formats" définit la page de code récupérée par l'option LC_CTYPE
, tandis que "Administrateur -> Langue pour les programmes non Unicode" définit la page de code de traduction pour les noms de fichier. Dans les pays occidentaux, le paramètre LC_CTYPE
correspond à quelque chose comme language_country.1252
, où 1252 est la page de code, également appelée «codage Windows-1252», qui est similaire (mais pas exactement identique) à ISO-8859-1. Au Japon, la page de codes 932 est généralement définie à la place et ainsi de suite pour les autres pays. Sous PHP, vous pouvez créer des fichiers dont le nom peut être exprimé avec la page de code actuelle. Inversement, les noms de fichiers et les chemins extraits du système de fichiers sont convertis d'octets UTF-16 à l'aide de la page de codes actuelle "optimale" .
Ce mappage étant approximatif, il est possible que certains caractères soient mutilés de manière imprévisible. Par exemple, Caffé Brillì.txt
serait renvoyé par dir()
en tant que PHP chaîne Caff\xE9 Brill\xEC.txt
comme prévu si la page de code actuelle est 1252, alors qu'elle renverrait le Caffe Brilli.txt
approximatif sur un système japonais car les voyelles accentuées sont absentes de la page de code 932 et puis remplacés par leurs voyelles "les mieux adaptées" non accentuées. Les caractères qui ne peuvent pas du tout être traduits sont récupérés sous la forme ?
(point d'interrogation). En général, sous Windows, il n’existe aucun moyen sûr de détecter de tels artefacts.
Plus de détails sont disponibles dans ma réponse au bogue n ° PHP. 47096 .
PHP 7.1 prend en charge les noms de fichiers UTF-8 sous Windows, sans tenir compte de la page de codes OEM.
Le problème est que Windows utilise utf-16 pour les chaînes de système de fichiers, alors que Linux et d'autres utilisent des jeux de caractères différents, mais souvent utf-8. Vous avez fourni une chaîne utf-8, mais celle-ci est interprétée comme un autre codage de jeu de caractères 8 bits sous Windows, par exemple Latin-1, puis le caractère non ascii, codé avec 2 octets dans utf-8, est traité comme suit: s'il s'agissait de 2 caractères sous Windows.
Une solution normale consiste à conserver votre code source à 100% en ascii et à avoir des chaînes ailleurs.
En utilisant l'extension com_dotnet
PHP, vous pouvez accéder au Scripting.FileSystemObject
de Windows, puis faire tout ce que vous voulez avec les noms de fichiers/dossiers UTF-8.
Je l'ai emballé comme un wrapper de flux PHP, il est donc très facile à utiliser:
Commencez par vérifier que l'extension com_dotnet
est activée dans votre php.ini
Activez ensuite l'encapsuleur avec:
stream_wrapper_register('win', 'Patchwork\Utf8\WinFsStreamWrapper');
Enfin, utilisez les fonctions auxquelles vous êtes habitué (mkdir, fopen, renommer, etc.), mais préfixez votre chemin avec win://
Par exemple:
<?php
$dir_name = "Depósito";
mkdir('win://' . $dir_name );
?>
Vous pouvez utiliser cette extension pour résoudre votre problème: https://github.com/kenjiuno/php-wfio
$file = fopen("wfio://多国語.txt", "rb"); // in UTF-8
....
fclose($file);
Je n'ai pas besoin d'écrire beaucoup, ça marche bien:
<?php
$dir_name = mb_convert_encoding("Depósito", "ISO-8859-1", "UTF-8");
mkdir($dir_name);
?>
Essayez l'assistant de texte CodeIgniter à partir de ce lien En savoir plus sur la fonction convert_accented_characters ()
Mon ensemble d'outils pour utiliser le système de fichiers avec UTF-8 sur Windows OU linux via PHP
et compatible avec le fichier de contrôle .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);
}
Ressources supplémentaires