Я не могу использовать mkdir для создания папок с символами UTF-8:
<?php
$dir_name = "Depósito";
mkdir($dir_name);
?>
Когда я просматриваю эту папку в проводнике Windows, имя папки выглядит так:
Depósito
Что мне необходимо сделать? Я использую php5.
Ответ 1
Просто перекодируйте строку в имя файла. Все символы, возвращаемые urlencode, допустимы в именах файлов (NTFS/HFS/UNIX), затем вы можете просто выполнить urldecode для имен файлов обратно в UTF-8 (или в любой другой кодировке, в которой они были).
Предостережения (все они применимы и к решениям ниже):
После url-кодирования имя файла должно быть меньше 255 символов (возможно, байт).
UTF-8 имеет несколько представлений для многих символов (используя объединение символов). Если вы не нормализуете UTF-8, у вас могут возникнуть проблемы с поиском с помощью glob или повторным открытием отдельного файла.
Вы не можете полагаться на scandir или подобные функции для альфа-сортировки. Вы должны выполнять urldecode для имен файлов, а затем использовать алгоритм сортировки, понимающий UTF-8 (и возможные коллизии форматов).
Ниже приведены менее привлекательные решения: более сложные и с большим количеством оговорок. В Windows обертка файловой системы PHP ожидает и возвращает строки ISO-8859-1 для имен файлов/директорий. Это дает вам два варианта:
Свободно использовать UTF-8 в именах файлов, но понимать, что не-ASCII символы будут выглядеть некорректно вне PHP. Символ UTF-8, не являющийся символом ASCII, будет храниться как несколько символов ISO-8859-1. Например, «ó» будет отображаться как «Ã³» в проводнике Windows.
Ограничьте имена ваших файлов/каталогов символами, представимыми в ISO-8859-1. На практике вы будете передавать строки в UTF-8 через utf8_decode перед использованием их в функциях файловой системы, а записи, которые выдает scandir, передавать через utf8_encode, чтобы получить оригинальные имена файлов в UTF-8.
Если любой байт, переданный в функцию файловой системы, совпадает с недопустимым символом файловой системы Windows в ISO-8859-1, результат не определен.
Windows может использовать кодировку, отличную от ISO-8859-1, в не английских локалях. Я предполагаю, что обычно это будет одна из ISO-8859-#, но это означает, что вам придется использовать mb_convert_encoding вместо utf8_decode.
По этой причине вы, вероятно, должны просто использовать транслитерацию для создания имен файлов.
Ответ 2
В Unix и Linux (и, возможно, в OS X тоже) текущая кодировка файловой системы задается параметром LC_CTYPE locale (см. функцию setlocale()). Например, она может иметь значение en_US.UTF-8, что означает кодировку UTF-8. Тогда имена файлов и пути к ним могут быть созданы с помощью fopen() или получены с помощью dir() с этой кодировкой.
В Windows PHP работает как «программа, не поддерживающая Юникод», тогда имена файлов преобразуются из UTF-16, используемого файловой системой (Windows 2000 и более поздние версии), в выбранную «кодовую страницу». Панель управления «Региональные и языковые параметры», панель вкладок «Форматы» устанавливает кодовую страницу, извлекаемую опцией LC_CTYPE, а «Администрирование -> Язык для программ, не поддерживающих Юникод» устанавливает кодовую страницу перевода для имен файлов. В западных странах параметр LC_CTYPE оценивается как что-то вроде language_country.1252, где 1252 — кодовая страница, также известная как «кодировка Windows-1252», которая похожа (но не совсем равна) на ISO-8859-1. В Японии вместо этого обычно устанавливается кодовая страница 932 и так далее для других стран. В PHP вы можете создавать файлы, имена которых могут быть выражены с помощью текущей кодовой страницы. И наоборот, имена файлов и пути, получаемые из файловой системы, преобразуются из UTF-16 в байты с использованием «наиболее подходящей» текущей кодовой страницы.
Это сопоставление является приблизительным, поэтому некоторые символы могут быть искажены непредсказуемым образом. Например, «Caffé Brillì.txt» будет возвращен dir() как PHP-строка «Caff\xE9 Brill\xEC.txt», как и ожидалось, если текущая кодовая страница равна 1252, в то время как в японской системе будет возвращена приблизительно «Caffe Brilli.txt», поскольку гласные с ударением отсутствуют в кодовой странице 932, а затем заменены на их «наиболее подходящие» гласные без ударения. Символы, которые не могут быть переведены вообще, извлекаются как «?» (знак вопроса). В общем, под Windows нет надежного способа обнаружить такие артефакты.
Ответ 3
Проблема в том, что Windows использует utf-16 для строк файловой системы, в то время как Linux и другие используют различные наборы символов, но часто utf-8. Вы предоставили строку utf-8, но она интерпретируется как другая 8-битная кодировка набора символов в Windows, возможно, Latin-1, и тогда не ascii символ, который кодируется 2 байтами в utf-8, обрабатывается как 2 символа в Windows. Лучшее решение — хранить исходный код на 100% в ascii, а строки располагать в другой кодировке.
Ответ 4
Мой набор инструментов для использования файловой системы с UTF-8 на Windows или Linux через PHP и совместимый с файлом .htaccess:
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);
}
Web