Перейти к содержимому

Как узнать кодировку текста php

  • автор:

PHP определение кодировки

Есть скрипт что пытается определить кодировку и сменить на WINDOWS-1251.
Вот основной кусок:

$from = mb_detect_encoding($cell,"auto"); print_r($from);echo"\n"; $cell = iconv( $from, "WINDOWS-1251//IGNORE", $cell ); 

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

print_r(mb_list_encodings()); print_r(mb_detect_order()); 

Вторая отдает скромненький массивчик:

Array ( [0] => ASCII [1] => UTF-8 ) 

Первая значительно больше. Причем в зависимости от версии PHP список чуть-чуть меняется.
Сперва грешил на это, но потом открыл файл в OpenOffice, который даже не предложил выбрать кодировки.
Установил какое расширение, где выбрал латин-1 => кирилица , и все гуд.
То есть latin-1 , подумал я, но он есть, как понял, в любой версии. Хотел первой строчкой получать список и подсовывать его в mb_detect_encoding , но там еще есть какой то порядок. В общем я запутался уже. Подскажите как нормально определить кодировку?
Или дополните по моему сабжу, если не получилось полной каши. Спасибо. UPD1:
Сегодня пробовал:

print_r(mb_check_encoding($cell,"WINDOWS-1251")); print_r(mb_check_encoding($cell,"ASCII")); print_r(mb_check_encoding($cell,"WINDOWS-1252")); print_r(mb_check_encoding($cell,"UTF-8")); print_r(mb_check_encoding($cell,"ISO-8859-1")); 

Все отдают 1.
Что означает?
Кодировка не верна или подходит любая??

mb_check_encoding

Проверяет, что для потока данных подходит выбранная кодировка. Если value является массивом ( array ), все ключи и значения проверяются рекурсивно. Функция может быть полезной для предотвращения так называемой «Атаки неправильной кодировкой».

Список параметров

Поток данных или массив ( array ) для проверки. Если не задан, функция проверит все входные данные с начала запроса.

Внимание

Начиная с PHP 8.1.0, опускание этого параметра или передача null устарело.

Возвращаемые значения

Возвращает true в случае успешного выполнения или false в случае возникновения ошибки.

Список изменений

Версия Описание
8.1.0 Вызов функции с null в качестве параметра value или без аргумента устарело.
8.0.0 Параметры value и encoding могут принимать значение null .
7.2.0 Функция теперь также принимает массив ( array ) в value . Ранее поддерживались только строки ( string ).

User Contributed Notes

There are no user contributed notes for this page.

  • Функции для работы с многобайтовыми строками
    • mb_​check_​encoding
    • mb_​chr
    • mb_​convert_​case
    • mb_​convert_​encoding
    • mb_​convert_​kana
    • mb_​convert_​variables
    • mb_​decode_​mimeheader
    • mb_​decode_​numericentity
    • mb_​detect_​encoding
    • mb_​detect_​order
    • mb_​encode_​mimeheader
    • mb_​encode_​numericentity
    • mb_​encoding_​aliases
    • mb_​ereg_​match
    • mb_​ereg_​replace_​callback
    • mb_​ereg_​replace
    • mb_​ereg_​search_​getpos
    • mb_​ereg_​search_​getregs
    • mb_​ereg_​search_​init
    • mb_​ereg_​search_​pos
    • mb_​ereg_​search_​regs
    • mb_​ereg_​search_​setpos
    • mb_​ereg_​search
    • mb_​ereg
    • mb_​eregi_​replace
    • mb_​eregi
    • mb_​get_​info
    • mb_​http_​input
    • mb_​http_​output
    • mb_​internal_​encoding
    • mb_​language
    • mb_​list_​encodings
    • mb_​ord
    • mb_​output_​handler
    • mb_​parse_​str
    • mb_​preferred_​mime_​name
    • mb_​regex_​encoding
    • mb_​regex_​set_​options
    • mb_​scrub
    • mb_​send_​mail
    • mb_​split
    • mb_​str_​pad
    • mb_​str_​split
    • mb_​strcut
    • mb_​strimwidth
    • mb_​stripos
    • mb_​stristr
    • mb_​strlen
    • mb_​strpos
    • mb_​strrchr
    • mb_​strrichr
    • mb_​strripos
    • mb_​strrpos
    • mb_​strstr
    • mb_​strtolower
    • mb_​strtoupper
    • mb_​strwidth
    • mb_​substitute_​character
    • mb_​substr_​count
    • mb_​substr
    • Copyright © 2001-2024 The PHP Group
    • My PHP.net
    • Contact
    • Other PHP.net sites
    • Privacy policy

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

    Иногда появляется необходимость определить кодировку текста. И в 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 секунд. (на моем компьютере).

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

    Выставляем кодировку UTF-8

    На сколько бы это глупо не казалось, но для удачного выставления кодировки необходимо выполнить целых 11(!) правил.
    Хочу зарание предупредить, если какая-то из настроек в .htaccess повлечет за собой ошибку 500, это значит, что хостинг запретил менять этот параметр на сервере. В таком случае проверьте тот факт, что у Вас UTF-8 и в случае чего обратитесь к админам хостинга.
    И для тех, кто попал на эту страницу с вопросами об Ajax: Ajax работает в кодировке UTF-8.

    Правило №1: Указываем в HTML верстке в теге первой строчкой, кроме случаев, где мы будем использовать тег , так как он так же как и кодировка имеет приоритет над расположением, следующий код:

    Правило №2: Указываем кодировку для PHP и самого файла, для этого нам необходимо выставить заголовок функцией header(). Выставляем его в самом начале нашего файла (абсолютно в самом начале), сразу после указания уровня вывода ошибок:

    Правило №3: Кодировка для подключения к к БД MySQL. Устанавливается после подключения к БД и выбора бд (mysql_connect, mysql_select_db). Если у нас модуль mysql:

    или улучшенный модуль mysqli:

    set_charset("utf8");

    Правило №4: Кодировка в .htaccess:

    AddDefaultCharset UTF-8

    Правило №5: Кодировка для библиотеки mb, начиная с версии php 5.4 можно не указывать, так как по умолчанию будет использоваться именно UTF-8. Ну а пока прописываем её в файле .htaccess:

    php_value mbstring.internal_encoding UTF-8

    Либо в самом PHP, что в итоге выполнит одни и те же действия:

    mb_internal_encoding("UTF-8");

    Правило №6: При сохранении файлов (обязательно ВСЕХ!) выбрать кодировку UTF-8 without BOM, повторюсь, without BOM — это необходимая настройка, в противном случае Ваш сайт не будет работать как надо. Для тех, кто пользуется удобной программой DreamWeaver:
    Modify => Page Properties => Title/Encoding и выставляем «Encoding: UTF-8», после чего нажимаем ReLoad, убираем галочку с BOM «Include Unicode Signature (BOM)». Apply + OK.
    Модификации => Свойства страницы => Заголовок/Кодировка и выставляем кодировку UTF-8. Нажимаем «перезагрузить», убрали галочку с Подключить Юникод Сигнатуры (BOM). Применить и OK.

    Правило №7: если на данный момент какой-то из текстов был введён на странице или в БД — его необходимо перенабрать. Дело в том, что символ в одной кодировке представляет один набор бит для русских символов, а в другой — другой. Именно поэтому необходимо его либо перенабрать, либо перекодировать. Современные программы имеют возможность перевести текст из одной кодировки в другую. Об этой возможности интересуйтесь в мануалах Ваших программ.

    Правило №8: Есть исключение, когда текст приходит к Вам на страницу с другого сайта в другой кодировке. Тогда на PHP есть удобная функция для перевода из одной кодировки в другую:

    Правило №9: Для строковых функций strlen, substr, необходимо использовать их аналоги на библиотеке mb_, а именно: mb_strlen, mb_substr, то есть к функции дописываем mb_ .

    Правило №10: Для работы с регулярными выражениями необходимо указывать модификатор u . Это обязательный параметр!

    Правило №11: Для CSS файлов указывается кодировка так:

    @charset "utf-8";

    В заключение скажу, что символы в кодировке WIN-1251 состоят из 1 байта, то есть 8 бит, а в свою очередь в кодировке UTF-8 символы могут состоять от 1 до 4 байт, всё дело в том, что кодировка UTF-8 позволяет создавать мультиязычные сайты, так как все существующие в мире символы в ней присутствуют.
    Ради любопытства русская буква в кодировке UTF-8 занимает 2 байта, именно поэтому за 1 символ функция strlen возвращает длину 2, то есть 2 байта, а mb_strlen возвращает уже правильную длину в 1 символ.

    Школа программирования © 2012-2024
    imbalance_hero | inpost@list.ru , admin@school-php.com
    account on phpforum | youtube channel

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *