Как использовать функции файловой системы в PHP, используя строки UTF-8?
-
20-09-2019 - |
Вопрос
Я не могу использовать mkdir
Для создания папок с символами UTF-8:
<?php
$dir_name = "Depósito";
mkdir($dir_name);
?>
Когда я просматриваю эту папку в Windows Explorer, имя папки выглядит так:
Depósito
Что я должен делать?
Я использую php5
Решение
Просто urlencode
Строка желала в качестве имени файла. Все Персонажи возвращены из 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. War не ASCII UTF-8 будет храниться как множество не замужем ISO-8859-1 символы. Например
ó
появится какó
В Windows Explorer.Ограничьте имена файла/каталогов символы, представленные в ISO-8859-1. Анкет На практике вы передадите свои строки UTF-8 через
utf8_decode
Перед использованием их в функциях файловой системы и передачи записиscandir
дает вам черезutf8_encode
Чтобы получить оригинальные имена файлов в UTF-8.
Обеспеченные в изобилии!
- Если есть байт Передается на функцию файловой системы соответствует Неверный символ файловой системы Windows В ISO-8859-1 вам не повезло.
- Окна май Используйте кодирование, отличное от ISO-8859-1 в неанглийских местах. Я предполагаю, что это обычно будет одним из ISO-8859-#, но это означает, что вам нужно использовать
mb_convert_encoding
вместоutf8_decode
.
Этот кошмар - почему вы, вероятно, должны просто транслитерат Чтобы создать имена файлов.
Другие советы
Под Unix и Linux (и, возможно, под OS X) и кодирование текущей файловой системы определяется LC_CTYPE
Параметр локали (см. Функцию setlocale()
) Например, это может оценить что -то вроде en_US.UTF-8
Это означает, что кодирование является UTF-8. Тогда имена файлов и их пути могут быть созданы с помощью fopen()
или извлечено dir()
с этим кодированием.
В соответствии с Windows PHP работает как «программа, не осведомленная об Unicode», затем имена файлов преобразуются туда-сюда из UTF-16, используемой файловой системой (Windows 2000 и более поздними) в выбранную «кодовую страницу». Панель управления «Региональные и языковые параметры», вкладка «Форматы» устанавливает кодовую страницу, полученную LC_CTYPE
Вариант, в то время как «Административный -> Язык для программ, не являющихся Unicode», устанавливает страницу кода перевода для имен файлов. В западных странах 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, а затем заменяются их «наиболее подходящими» гласными. Персонажи, которые не могут быть переведены вообще, получены как ?
(вопросительный знак). В целом, под окнами нет безопасного способа обнаружить такие артефакты.
Более подробная информация доступна в моем ответе на PHP ошибка №. 47096.
PHP 7.1 поддерживает имена файлов UTF-8 в Windows, игнорирующих OEM-кодискую страницу.
Проблема в том, что Windows использует UTF-16 для строк файловой системы, тогда как Linux и другие используют разные наборы символов, но часто UTF-8. Вы предоставили строку UTF-8, но она интерпретируется как еще один 8-битный набор символов, кодирующий в окнах, возможно, латинс-1, а затем символ не ASCII, который закодирован с 2 байтами в UTF-8, обрабатывается как Если это было 2 символа в Windows.
Нормальное решение состоит в том, чтобы сохранить ваш исходный код на 100% в ASCII и иметь струны где -то еще.
С использованием com_dotnet
PHP расширение, вы можете получить доступ к Windows ' Scripting.FileSystemObject
, а затем сделайте все, что вы хотите с именами файлов UTF-8/папок.
Я упаковал это как обертка PHP -потока, так что это очень легко использовать:
Сначала убедитесь, что com_dotnet
расширение включено в вашем php.ini
Затем включите обертку с:
stream_wrapper_register('win', 'Patchwork\Utf8\WinFsStreamWrapper');
Наконец, используйте функции, к которым вы привыкли (Mkdir, Fopen, переименование и т. Д.), Но префикс ваш путь с помощью 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);
Попробуйте Text -Text Text от эта ссылкаПрочитайте о функции 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);
}
Дополнительные ресурсы
Мне не нужно много писать, это работает хорошо:
<?php
$dir_name = mb_convert_encoding("Depósito", "ISO-8859-1", "UTF-8");
mkdir($dir_name);
?>