кодирование в UTF-8 - есть ли окончательное решение?


Я просмотрел весь Интернет, я просмотрел SO, документацию по PHP и многое другое.

Кажется нелепой проблемой, для которой нет стандартного решения. Если вы получаете неизвестный набор символов, и в нем есть странные символы (например, английские кавычки), существует ли стандартный способ преобразовать их в UTF-8?

Я видел много грязных решений, использующих множество функций и проверок, и ни одно из них определенно не будет работать.

Кто-нибудь придумал свой собственная функция или решение, которое всегда работает?


РЕДАКТИРОВАТЬ

Многие люди отвечали, что "это неразрешимо" или что-то в этом роде. Я понимаю это сейчас, но никто не дал никакого решения, которое работало бы, кроме utf8_encode, которое очень ограничено. Какие существуют методы борьбы с этим? Что такое лучший метод?

Author: David, 2010-06-12

4 answers

Причина, по которой вы видели так много сложных решений этой проблемы, заключается в том, что по определению она неразрешима. Процесс кодирования строки текста не является детерминированным. Можно создавать различные комбинации текста и кодировок, которые приводят к одному и тому же потоку байтов. Поэтому, строго говоря, логически невозможно определить кодировку, набор символов и текст из потока байтов.

В действительности можно достичь результатов, которые являются "достаточно близкими", используя эвристические методы, потому что существует конечный набор кодировок, с которыми вы столкнетесь в дикой природе, и с достаточно большим образцом программа может определить наиболее вероятную кодировку. Будут ли результаты достаточно хорошими, зависит от приложения.

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

Например, если я наберу букву Ä на своей немецкой клавиатуре и опубликую ее на странице в кодировке UTF-8, на сервер будет отправлено 2 байта (XC3 x84). Это допустимая строка EBCDIC, представляющая букву C и d. Это также допустимая строка ANSI, которая представляет 2 символа "и". Однако, независимо от того, что я пытаюсь, невозможно вставить строку в кодировке ANSI в форму браузера и ожидать, что она будет интерпретироваться как UTF-8 - потому что операционная система знает, что я вставляю ANSI (я скопировал текст с Textpad, где я создал текстовый файл в кодировке ANSI) и перекодирует его в UTF-8, в результате чего поток байтов xC3 x83 x2 x80 x9E.

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

К сожалению, для загруженных файлов проблема остается. Единственное надежное решение, которое я см., чтобы показать пользователю раздел файла и спросить, правильно ли он был интерпретирован, и перебирать множество различных кодировок, пока это не произойдет.

Или мы могли бы разработать эвристический метод, который рассматривает появление определенных символов в разных языках. Допустим, я загрузил свой текстовый файл, содержащий два байта xC3 x84. Другой информации нет - всего два байта в файле. Этот метод мог бы обнаружить, что буква Ä довольно распространена в немецком тексте, но буквы "и" вместе встречаются редко на любом языке и, таким образом, определяют, что кодировка моего файла действительно UTF-8. Это грубый уровень сложности, с которым приходится иметь дело такому эвристическому методу, и чем больше статистических и лингвистических фактов он может использовать, тем надежнее будут его результаты.

 9
Author: cdonner, 2010-06-14 01:51:51

Нет. Всегда нужно знать, в каком наборе символов находится строка. Угадывание набора символов с помощью функции обнюхивания ненадежно (хотя в большинстве ситуаций в западном мире обычно происходит путаница между ISO-8859-1 и UTF-8).

Но почему вам приходится иметь дело с неизвестными наборами символов? Для этого нет общего решения, потому что общая проблема не должна существовать в первую очередь. Каждая веб-страница и источник данных могут и должны иметь определение набора символов, а если нет, то следует попросить администратора этого ресурса добавить его.

(Не хочу показаться умником, но это единственный способ справиться с этим хорошо.)

 11
Author: Pekka 웃, 2010-06-11 21:05:01

Пекка прав насчет ненадежности, но если вам нужно решение и вы готовы рискнуть, и у вас есть доступная библиотека mbstring, этот фрагмент должен работать:

function forceToUtf8($string) {
    if (!mb_check_encoding($string)) {
        return false;
    }
    return mb_convert_encoding($string, 'UTF-8', mb_detect_encoding($string));
} 
 1
Author: Dereleased, 2010-06-11 21:11:42

Если я не ошибаюсь, есть что-то под названием utf8encode... это хорошо работает, ЗА исключением случаев, когда вы уже находитесь в utf8

Http://php.net/manual/en/function.utf8-encode.php

 0
Author: Fire-Dragon-DoL, 2010-06-14 01:57:17