Определение кодировки текста в PHP вместо mb_detect_encoding

в 6:27, , рубрики: encodingcyrillic, ibm866, iconv, iso-8859-5, koi8-r, mb_detect_encoding, php, utf-8, windows-1251, кодировки текста, Программирование, Проектирование и рефакторинг

Существует несколько кодировок символов кириллицы.

При создании сайтов в Интернете обычно используют:

  • utf-8
  • windows-1251
  • koi8-r

Еще популярные кодировки:

  • iso-8859-5
  • ibm866
  • mac-cyrillic

Вероятно это не весь список, это те кодировки с которыми я часто сталкиваюсь.

Иногда появляется необходимость определить кодировку текста. И в PHP даже функция для этого есть:

mb_detect_encoding

но как писал m00t
в статье Определение кодировки текста в PHP — обзор существующих решений плюс еще один велосипед

Если кратко — он не работает.

Прочитав статьи m00t я не вдохновился его методом и нашел вот такое решение: Определение кодировки текста в PHP и Python
Как сказал m00t

опять коды символов

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

Недавно решил переписать проект где использовал эту функцию, нашел готовый пакет на packagist.org cnpait/detect_encoding, в котором кодировка определяется методом m00t

При этом указанный пакет был установлен более 1200 раз, значит не у меня одного периодически возникает задача определения кодировки текста.

Мне бы установить этот пакет и успокоиться, но я решил «заморочиться».

В общем, сделал свой пакет: onnov/detect-encoding.

Как его использовать написано в README.md

А о его тестировании и сравнении с пакетом cnpait/detect_encoding напишу.

Методика тестирования

Берем большой текст: Tolstoy — Anna Karenina
Всего — 1'701'480 знаков

Убираем все лишнее, оставляем только кириллицу:

$text = preg_replace('/[^а-яА-Я]/ui', '', $text);

Осталось 1'336'252 кирилистических знаков.

В цикле берем часть текста (5, 15, 30,… символов) преобразуем в известную кодировку и пытаемся определить кодировку скриптом. Затем сравниваем правильно или нет.

Вот таблица в которой слева кодировки, сверху количество символов по которому определяем кодировку, в таблице результат достоверности в %%

letters -> 5 15 30 60 120 180 270
windows-1251 99.13 98.83 98.54 99.04 99.73 99.93 100.0
koi8-r 99.89 99.98 100.0 100.0 100.0 100.0 100.0
iso-8859-5 81.79 99.27 99.98 100.0 100.0 100.0 100.0
ibm866 99.81 99.99 100.0 100.0 100.0 100.0 100.0
mac-cyrillic 12.79 47.49 73.48 92.15 99.30 99.94 100.0

Наихудшая точность с мак-кириллицей, вам нужно как минимум 60 символов, чтобы определить эту кодировку с точностью 92,15%. Кодировка Windows-1251 также имеет очень низкую точность. Это связано с тем, что номера их символов в таблицах сильно пересекаются.

К счастью, кодировки mac-cyrillic и ibm866 не используются для кодирования веб-страниц.

Попробуем без них:

letters -> 5 10 15 30 60
windows-1251 99.40 99.69 99.86 99.97 100.0
koi8-r 99.89 99.98 99.98 100.0 100.0
iso-8859-5 81.79 96.41 99.27 99.98 100.0

Точность определения высока даже в коротких предложениях от 5 до 10 букв. А для фраз из 60 букв точность определения достигает 100%. А еще, определение кодировки выполняется очень быстро, например, текст длиной более 1 300 000 символов кириллицы проверяется за 0 00096 секунд. (на моем компьютере)

А какие результаты покажет статистический способ описанный m00t:

letters -> 5 10 15 30 60
windows-1251 88.75 96.62 98.43 99.90 100.0
koi8-r 85.15 95.71 97.96 99.91 100.0
iso-8859-5 88.60 96.77 98.58 99.93 100.0

Как видим результаты определения кодировки хорошие. Скорость работы скрипта высокая, особенно на коротких текстах, на огромных текстах скорость значительно уступает. Текст длиной более 1 300 000 символов кириллицы проверяется за 0 32 секунд. (на моем компьютере).

Мои выводы

  • Обе методики дают хорошие результаты.
  • Точность методов близка.
  • Скорость определения по кодам символов выше на больших текстах, но вряд ли это имеет большое значение, т.к. мало вероятно, что кто то будет проверять такие огромные тексты.
  • У статистического метода еще есть потенциал для увеличения точности определения кодировок.

Какой метод использовать решать вам. В принципе, можно использовать сразу оба.

Автор: oka_volga

Источник


* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js