2009-07-07 4 views
3

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

Я установил PHP для использования UTF8 в качестве кодировки по умолчанию через php_ini, а также для установки mb_internal_encoding. Я проверил строчную кодировку с файловым файлом PHP, и он выходит как UTF8, как и следовало ожидать. Еще несколько раз, я решил, что символ é, который завершает вкладку терминала, сравнивает его с 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?

ответ

4

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

В PHP 5.3 был введен a new set of functions, который позволяет нормализовать строку юникода для определенной декомпозиции. По-видимому, существует четыре стандарта разложения, которые вы можете разложить на строку unicode. Python имеет нормализацию юникода, начиная с версии 2.3, с помощью unicode.normalize.This article на обработку python строк в Юникоде было полезно для понимания кодирования/обработки строк немного лучше.

Вот краткий пример о нормализации Юникода FilePath:

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

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

3

Три последовательность байтов на самом деле utf8 представление e (0x65) с последующим combining ´ (0xcc 0x81), в то время как 0xC3 0xa9 стоит «непосредственно» для é.
Совместимость с utf-8 должна быть в курсе возможных разложений, но я не знаю, как вы можете включить это (и, возможно, перекомпилировать источник php) на mac.
Лучшее, что я могу предложить, это описание "Using UTF-8 with Gentoo".

1

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

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

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

Смежные вопросы