Существует несколько кодировок символов кириллицы.
При создании сайтов в Интернете обычно используют:
- 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