Угадать кодировку текста, представленного как byte [] в Java

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

Стоит отметить:

  • Никаких дополнительных метаданных нет. Массив байтов - это буквально единственный доступный вход.
  • Очевидно, что алгоритм обнаружения не будет на 100% правильным. Если алгоритм верен более чем в 80% случаев, этого достаточно.

person knorv    schedule 04.11.2009    source источник
comment
stackoverflow.com/questions/373081 может помочь   -  person Chris    schedule 05.11.2009


Ответы (7)


Следующий метод решает проблему с использованием juniversalchardet, который является портом Java библиотеки обнаружения кодировки Mozilla.

public static String guessEncoding(byte[] bytes) {
    String DEFAULT_ENCODING = "UTF-8";
    org.mozilla.universalchardet.UniversalDetector detector =
        new org.mozilla.universalchardet.UniversalDetector(null);
    detector.handleData(bytes, 0, bytes.length);
    detector.dataEnd();
    String encoding = detector.getDetectedCharset();
    detector.reset();
    if (encoding == null) {
        encoding = DEFAULT_ENCODING;
    }
    return encoding;
}

Приведенный выше код был протестирован и работает так, как задумано. Просто добавьте juniversalchardet-1.0.3.jar в путь к классам.

Я протестировал как juniversalchardet, так и jchardet. Мое общее впечатление таково, что juniversalchardet обеспечивает лучшую точность обнаружения и более приятный API из двух библиотек.

person knorv    schedule 05.11.2009
comment
мое требование к проекту: если данные не в utf8 (после обнаружения), затем преобразовать их в utf8, как это сделать? - person coding_idiot; 21.02.2013
comment
@coding_idiot использует предполагаемую кодировку для преобразования в строку, а затем получает байты utf-8: new String(bytes, guessedEncoding).getBytes("utf-8"). - person Brett Okken; 19.06.2014
comment
Не очень доволен этим. См. github.com/albfernandez/juniversalchardet/issues/22. - person Sxilderik; 09.01.2018
comment
juniversalchardet также доступен в maven. groupId: com.googlecode.juniversalchardet, artifactId: juniversalchardet. - person Aleksandr Erokhin; 09.11.2018

Также существует Apache Tika - набор инструментов для анализа контента. Он может угадать тип пантомимы и кодировку. Обычно предположение оказывается верным с очень высокой вероятностью.

person Thomas Mueller    schedule 20.09.2010

Вот мой любимый: https://github.com/codehaus/guessencoding

Работает это так:

  • Если есть спецификация UTF-8 или UTF-16, верните эту кодировку.
  • Если ни в одном из байтов не установлен старший бит, верните ASCII (или вы можете заставить его вернуть 8-битную кодировку по умолчанию).
  • Если есть байты с установленным старшим битом, но они расположены по правильным шаблонам для UTF-8, верните UTF-8.
  • В противном случае верните кодировку платформы по умолчанию (например, windows-1252 в системе Windows с английской локалью).

Это может показаться чересчур упрощенным, но в моей повседневной работе точность превышает 90%.

person Alan Moore    schedule 05.11.2009

Ответ Чи кажется наиболее многообещающим для реального использования. Я просто хочу добавить, что, по словам Джоэла Спольски, в свое время Internet Explorer использовал алгоритм угадывания на основе частоты:

http://www.joelonsoftware.com/articles/Unicode.html

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

person Rooke    schedule 05.11.2009

Ознакомьтесь с jchardet

person Chi    schedule 05.11.2009
comment
Уточните, пожалуйста, почему вы считаете jchardet лучшей библиотекой? - person knorv; 05.11.2009
comment
@chi, как преобразовать в utf8, если кодировка не utf8. - person coding_idiot; 21.02.2013

Должны быть вещи уже доступны

поиск Google показал icu4j

or

http://jchardet.sourceforge.net/

person gomesla    schedule 05.11.2009
comment
Я вроде как знаю, как использовать Google, но вопрос конкретно спрашивает, что лучше всего [..]. Итак, что лучше: icu4j, jchardet или какая-нибудь другая библиотека? - person knorv; 05.11.2009