Я не могу использовать mkdir для создания папок с символами UTF-8.
<?php $dir_name = "Depósito"; mkdir($dir_name ); ?>
Но, когда я просматриваю эту папку в Проводнике Windows, имя папки выглядит следующим образом:
Depósito
Что мне делать?
Просто urlencode
строку в качестве имени файла. Все символы, возвращаемые с urlencode
, действительны в именах файлов (NTFS / HFS / UNIX), тогда вы можете просто urldecode
имена файлов в UTF-8 (или какую бы кодировку они не были).
Предостережения (все применимы также к решениям ниже):
glob
или повторным открытием отдельного файла. scandir
или подобные функции для альфа-сортировки. Вы должны urldecode
имена файлов, а затем использовать алгоритм сортировки, который знает UTF-8 (и сортировки). Ниже представлены менее привлекательные решения, более сложные и с большим количеством оговорок.
В Windows оболочка файловой системы PHP ожидает и возвращает строки ISO-8859-1 для имен файлов / каталогов. Это дает вам два варианта:
Используйте UTF-8 свободно в своих именах файлов, но поймите, что символы, отличные от ASCII, будут отображаться некорректно за пределами PHP. Символ не-ASCII UTF-8 будет храниться как несколько одиночных символов ISO-8859-1. Например, в Windows Explorer будет отображаться как ó
.
Ограничьте имена файлов / каталогов символами, представленными в ISO-8859-1 . На практике вы передадите свои строки UTF-8 через utf8_decode
перед их использованием в функциях файловой системы и передадите записи, которые scandir
дает вам через utf8_encode
чтобы получить исходные имена файлов в UTF-8.
Осторожно!
mb_convert_encoding
вместо utf8_decode
. Этот кошмар – это то, почему вы должны просто транслитерировать, чтобы создавать имена файлов.
В Unix и Linux (и, возможно, в OS X тоже), текущая кодировка файловой системы задается параметром locale LC_CTYPE
(см. Функцию setlocale()
). Например, он может оценивать что-то вроде en_US.UTF-8
что означает, что кодировка UTF-8. Затем имена файлов и их пути могут быть созданы с помощью fopen()
или получены с помощью dir()
с помощью этой кодировки.
В Windows, PHP работает как «программа, не поддерживающая Unicode», тогда имена файлов преобразуются обратно и вперед из 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 нет безопасного способа обнаружения таких артефактов.
Более подробные сведения доступны в моем ответе на ошибку PHP. 47096 .
Проблема в том, что Windows использует utf-16 для строк файловой системы, тогда как Linux и другие используют разные наборы символов, но часто utf-8. Вы указали строку utf-8, но это интерпретируется как еще одна 8-битная кодировка символов в Windows, возможно, Latin-1, а затем символ не-ascii, который закодирован с помощью 2 байтов в utf-8, обрабатывается как если в Windows это было 2 символа.
Нормальным решением является сохранение исходного кода на 100% в ascii и наличие строк в другом месте.
PHP 7.1 поддерживает имена файлов UTF-8 в Windows, не обращая внимания на кодовую страницу OEM.
Благодарю.
Используя расширение com_dotnet
PHP, вы можете получить доступ к Windows Scripting.FileSystemObject
, а затем сделать все, что хотите, с именами файлов / папок UTF-8.
Я упаковал это как оболочку потока PHP, поэтому он очень прост в использовании:
Сначала убедитесь, что расширение com_dotnet
включено в вашем php.ini
затем включите оболочку с помощью:
stream_wrapper_register('win', 'Patchwork\Utf8\WinFsStreamWrapper');
Наконец, используйте функции, к которым вы привыкли (mkdir, fopen, rename и т. Д.), Но префикс вашего пути с помощью win://
Например:
<?php $dir_name = "Depósito"; mkdir('win://' . $dir_name ); ?>
Вы можете использовать это расширение для решения своей проблемы: https://github.com/kenjiuno/php-wfio
$file = fopen("wfio://多国語.txt", "rb"); // in UTF-8 .... fclose($file);
Попробуйте использовать CodeIgniter Text helper из этой ссылки. Читайте о функции convert_accented_characters (), это может быть оценено
Мой набор инструментов для использования файловой системы с 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); }
Дополнительные ресурсы