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