Имена файлов UTF8 в PHP и различных кодировках Юникода


У меня есть файл, содержащий символы Юникода, на сервере под управлением Linux. Если я подключусь по SSH к серверу и использую завершение вкладки для перехода к файлу/папке, содержащей символы юникода, у меня не возникнет проблем с доступом к файлу/папке. Проблема возникает, когда я пытаюсь получить доступ к файлу через PHP (функция, с которой я обращался к файловой системе, была stat). Если я выведу путь, сгенерированный PHP-скриптом, в браузер и вставлю его в терминал, файл также, похоже, существует (хотя глядя на терминал, пути к файлам точно такие же).

Я настроил PHP на использование UTF8 в качестве кодировки по умолчанию через php_ini, а также установил mb_internal_encoding. Я проверил кодировку строки пути к файлу PHP, и она выходит как UTF8, как и должно быть. Покопавшись еще немного, я решил hexdump символ é, который является завершением вкладки терминала, и сравнить его с hexdump "обычным" символом é, созданным с помощью PHP-скрипта или вручную введя символ с клавиатуры (опция+e+e в os x). Вот результат:

echo -n é | hexdump
0000000 cc65 0081                              
0000003
echo -n é | hexdump
0000000 a9c3                                   
0000002

Символ é, который позволяет правильно ссылаться на файл в терминале, является 3-байтовым. Я не уверен, куда идти дальше, какую кодировку мне следует использовать в PHP? Должен ли я преобразовывать путь в другую кодировку с помощью iconv или mb_convert_encoding?

Author: iloveitaly, 2009-07-07

3 answers

Благодаря советам, приведенным в двух ответах, я смог покопаться и найти некоторые методы нормализации различных разложений юникода данного символа. В ситуации, с которой я столкнулся, я получал доступ к файлам, созданным приложением OS X Carbon. Это довольно популярное приложение, и поэтому его имена файлов, по-видимому, соответствуют определенной декомпозиции юникода.

В PHP 5.3 был введен новый набор функций , позволяющий нормализовать юникод строка для определенной декомпозиции. По-видимому, существует четыре стандарта декомпозиции, в которые вы можете разложить строку юникода. Python имеет возможности нормализации юникода с версии 2.3 через юникод.нормализовать. Эта статья об обработке строк юникода в python помогла немного лучше понять кодировку/обработку строк.

Вот краткий пример нормализации пути к файлу в юникоде:

filePath = unicodedata.normalize('NFD', filePath)

Я обнаружил, что формат NFD работает для все мои цели, я задаюсь вопросом, является ли это стандартной декомпозицией для имен файлов в юникоде.

 4
Author: iloveitaly, 2009-12-19 20:25:12

Трехбайтовая последовательность на самом деле является представлением utf8 e (0x65), за которым следует объединение (0xcc 0x81), в то время как 0xc3 0xa9 означает "напрямую" для é.
Параметры сортировки с поддержкой utf-8 должны быть осведомлены о возможных раскладках, но я не знаю, как вы можете включить это (и, возможно, перекомпилировать исходный код php) на mac.
Лучшее, что я могу предложить, это описание "Использование UTF-8 с Gentoo".

 3
Author: VolkerK, 2009-07-07 08:32:45

Во-первых: Вы должны стараться избегать наложения семантики на имена файлов. Я действительно не могу сказать, почему PHP генерирует имена файлов в вашем сценарии, поэтому я не могу предложить, как вы должны применять это правило.

Различные (двухбайтовые и трехбайтовые) представления é являются кодировками UTF-8 составленных и разложенных вариантов этого символа в Юникоде. В Юникоде это разные способы представления одного и того же визуального символа. Юникод имеет концепцию "канонизации" в в котором все представления одного и того же символа преобразуются в одно представление, что-то вроде сжатия двух строк в нижний регистр для выполнения сравнения без регистра.

Linux не выполняет канонизацию или любую другую автоматическую обработку имен файлов, поэтому файл может быть назван предварительно составленными (например, двухбайтовой последовательностью) или разложенными (например, трехбайтовой последовательностью) символами или любым сочетанием этих двух, это зависит от того, кто назвал файл. Если вы создаете файлы, вы можно было бы установить политику (например, всегда использовать предварительно составленные символы) и написать некоторый код для ее применения. В противном случае вы не можете полагаться здесь на какое-либо конкретное правило.

 1
Author: tialaramex, 2009-07-14 17:41:44