Как использовать функции файловой системы в PHP, используя строки UTF-8?

StackOverflow https://stackoverflow.com/questions/1525830

Вопрос

Я не могу использовать 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 для имен файлов/каталогов. Это дает вам два варианта:

  1. Используйте UTF-8 свободно в ваших именах файлов, но поймите, что не ASCII символы будут выглядеть неверно Вне PHP. War не ASCII UTF-8 будет храниться как множество не замужем ISO-8859-1 символы. Например ó появится как ó В Windows Explorer.

  2. Ограничьте имена файла/каталогов символы, представленные в 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 -потока, так что это очень легко использовать:

https://github.com/nicolas-grekas/patchwork-utf8/blob/lab-windows-fs/class/patchwork/utf8/winfsstreamwrapper.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);
?>
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top