Кириллица в php коде
Определение кодировки текста в PHP — обзор существующих решений плюс еще один велосипед
Столкнулся с задачей — автоопределение кодировки страницы/текста/чего угодно. Задача не нова, и велосипедов понапридумано уже много. В статье небольшой обзор найденного в сети — плюс предложение своего, как мне кажется, достойного решения.
Если кратко — он не работает.
Давайте смотреть:
Как видим, на выходе — полная каша. Что мы делаем, когда непонятно почему так себя ведет функция? Правильно, гуглим. Нашел замечательный ответ.
Чтобы окончательно развеять все надежды на использование mb_detect_encoding(), надо залезть в исходники расширения mbstring. Итак, закатали рукава, поехали:
Постить полный текст метода не буду, чтобы не засорять статью лишними исходниками. Кому это интересно посмотрят сами. Нас истересует строка под номером 593, где собственно и происходит проверка того, подходит ли символ под кодировку:
Вот основные фильтры для однобайтовой кириллицы:
Windows-1251 (оригинальные комментарии сохранены)
ISO-8859-5 (тут вообще все весело)
Как видим, ISO-8859-5 всегда возвращает TRUE (чтобы вернуть FALSE, нужно выставить filter->flag = 1).
Когда посмотрели фильтры, все встало на свои места. CP1251 от KOI8-R не отличить никак. ISO-8859-5 вообще если есть в списке кодировок — будет всегда детектиться как верная.
В общем, fail. Оно и понятно — только по кодам символов нельзя в общем случае узнать кодировку, так как эти коды пересекаются в разных кодировках.
2. Что выдает гугл
А гугл выдает всякие убожества. Даже не буду постить сюда исходники, сами посмотрите, если захотите (уберите пробел после http://, не знаю я как показать текст не ссылкой):
http:// deer.org.ua/2009/10/06/1/
http:// php.su/forum/topic.php?forum=1&topic=1346
3. Поиск по хабру
2) на мой взгляд, очень интересное решение: habrahabr.ru/blogs/php/27378/#comment_1399654
Минусы и плюсы в комменте по ссылке. Лично я считаю, что только для детекта кодировки это решение избыточно — слишком мощно получается. Определение кодировки в нем — как побочный эффект ).
4. Собственно, мое решение
Идея возникла во время просмотра второй ссылки из прошлого раздела. Идея следующая: берем большой русский текст, замеряем частоты разных букв, по этим частотам детектим кодировку. Забегая вперед, сразу скажу — будут проблемы с большими и маленькими буквами. Поэтому выкладываю примеры частот букв (назовем это — «спектр») как с учетом регистра, так и без (во втором случае к маленькой букве добавлял еще большую с такой же частотой, а большие все удалял). В этих «спектрах» вырезаны все буквы, имеющие частоты меньше 0,001 и пробел. Вот, что у меня получилось после обработки «Войны и Мира»:
Спектры в разных кодировках (ключи массива — коды соответствующих символов в соответствующей кодировке):
Далее. Берем текст неизвестной кодировки, для каждой проверяемой кодировки находим частоту текущего символа и прибавляем к «рейтингу» этой кодировки. Кодировка с бОльшим рейтингом и есть, скорее всего, кодировка текста.
Результаты
У-упс! Полная каша. А потому что большие буквы в CP1251 обычно соответствуют маленьким в KOI8-R. А маленькие буквы используются в свою очередь намного чаще, чем большие. Вот и определяем строку капсом в CP1251 как KOI8-R.
Пробуем делать без учета регистра («спектры» case insensitive)
Как видим, верная кодировка стабильно лидирует и с регистрозависимыми «спектрами» (если строка содержит небольшое количество заглавных букв), и с регистронезависимыми. Во втором случае, с регистронезависимыми, лидирует не так уверенно, конечно, но вполне стабильно даже на маленьких строках. Можно поиграться еще с весами букв — сделать их нелинейными относительно частоты, например.
5. Заключение
В топике не расмотрена работа с UTF-8 — тут никакий принципиальной разницы нету, разве что получение кодов символов и разбиение строки на символы будет несколько длиннее/сложнее.
Эти идеи можно распространить не только на кириллические кодировки, конечно — вопрос только в «спектрах» соответствующих языков/кодировок.
P.S. Если будет очень нужно/интересно — потом выложу второй частью полностью работающую библиотеку на GitHub. Хотя я считаю, что данных в посте вполне достаточно для быстрого написания такой библиотеки и самому под свои нужды — «спектр» для русского языка выложен, его можно без труда перенести на все нужные кодировки.
UPDATED
В комментариях проскочила замечательная функция, ссылку на которую я опубликовал под графом «убожество». Может быть погорячился со словами, но уж как опубликовал, так опубликовал — редактировать такие вещи не привык. Чтобы не быть голословным, давайте разберемся, работает ли она на 100%, как об этом говорит предполагаемый автор.
1) будут ли ошибки при «нормальной» работе этой функции? Предположим, что контент у нас на 100% валидный.
ответ: да, будут.
2) определит ли она что-нибудь кроме UTF-8 и не-UTF-8?
ответ: нет, не определит.
Проблема с кириллицей в php
Проект разрабатывается в кодировке utf-8. Столкнулся с проблемой обработки строк с символами кириллицы. Код
Т.е. для кириллицы функция не работает.
Что необходимо сделать, чтобы на выходе вместо “Доп�” получить “Дополни”?
4 ответа 4
Если коротко, то для мультибайтовых кодировок используют mb_substr()
Если сайт разрабатывается, как вы пишите, в UTF-8, значит надо разрабатывать UTF-8. Чтобы все мультибайтовые функции работали по умолчанию с разрабатываемой кодировкой, ее надо задать в самом начале (и желательно проверить, задалась или нет):
Если все ок, можете юзать все mb_ без прописки кодировки.
Забыл написать, почему это важно, ну, если вы разрабатываете. Потому что при использовании имени функции в качестве callback прописывать кодировку будет некуда.
mb_substr() вместо substr()
Чтобы в PHP работать с кириллическими строками посимвольно(включая извлечение подстроки и др.) нужно использовать специальные функции: http://php.net/manual/ru/ref.mbstring.php.
Всё из-за того, что на латинице 1 символ = 1 бит, поэтому:
Но кирилические символы занимают 2 бита, поэтому:
При этом можно это учитывать и работать в таком ключе:
Или разбить строку через str_split, указав split_length = 2:
Но так лучше не делать, потому что таким образом нельзя будет работать теперь с латиницей и остальными символами:
Кстати, чтобы нормально разделить сроку с русскими символами на массив символов, то лучше всего это делать так:
Что изменить, чтобы кириллица выводилась правильно из программы, запускаемой из PHP?
Меня не слушаются настройки кодировки cайта (Apache+PHP7.2 на Ubuntu).
Есть две утилиты конвертации документов doc в txt.
В консоли (Linux) обе отображают кириллицу корректно! А на сайте одна выводит латиницей, другая вопросиками.
В самом начале страницы index.php я указываю, как положено
И сharset влияет на отображение русского текста в операторе echo. Если я выбираю utf-8, то echo выводит текст русскими буквами:
echo “Русский”;
Но вывод двух утилит не изменяется ни при каких кодировках!
catdoc
Вообще-то мне и не нужно, чтобы на сайте был вывод из этих утилит. Мне нужно конвертировать их вывод в UTF-8 и передать дальше. Но я не могу конвертировать, пока не определю кодировку и подумал, что проще всего определить на сайте.
shell_exec это плохой вариант по части безопасноти. Попробуйте PHPOffice использовать. Пример смог найти только в коде теста, но думаю что при желании можно будет разобраться: https://github.com/PHPOffice/PHPWord/blob/develop/.
Я изменил вопрос, так как не там устанавливал кодировку. Нужно было в самом начале кода рнр ставить оператор header, а я менял в рнр.ini и в заголовке HTML. Теперь я убрал вообще HTML и вывод echo СТАЛ ЗАВИСЕТЬ от кодировки в headere. То есть русские буквы в echo “Русский текст”; стали видны только при установке utf-8 в headere.
Да я попробовал по Вашему совету mb_internal_encoding.
Ну она устанавливает какую-то переменную для библиотеки mb и сама же ее считывает и зачем мне она? Пример на phpword мне тоже cейчас не нужен, так как у меня файлы doc, а не docx.
У меня проблема в том, что не меняется вывод утилит на экран (через echo), независимо от того, что я изменяю header. Что мне нужно изменить, чтобы они выводили по русски?
В общем проблема оказалась вот в чем:
Оказалось, что для правильного отображения кириллицы на сайте нужно обязательно указать в параметрах catdoc одну из русских кодировок utf-8, koi8-r, cp866, cp1251 (не windows-1251). Без этого ключа вывод на сайте идет латиницей, несмотря на header.
Если я ставлю одну из этих кодировок, то вывод на экране зависит от установки в headere!
Проблемы с кодировкой при рисовании текста в PHP
В прошлой статье мы с Вами обсуждали рисование текста в PHP, и в конце статья я Вам сообщил, что таким способом Вы русские буквы (кириллицу) не выведите. И как рисовать русские буквы на изображении в PHP мы с Вами разберём в этой статье.
Давайте для начала разберём, почему так происходит, почему кириллицу PHP не рисует. Всё дело в том, что встроенные шрифты в PHP не содержат региональной привязки, поэтому русские буквы и не выводятся. Способов выхода из этой ситуации несколько, однако, мы с Вами разберём самый простой и, на мой взгляд, лучший вариант. Заключается он в переводе всех кириллических символов в Unicode. И для этого мы используем функцию iconv(). Не могу вспомнить, говорил я об этой очень полезной функции или нет, но она занимается переводом из одной кодировки в другую. Ладно, давайте приведу пример:
За мою уже достаточно долгую практику, функцию iconv() я использовал столько раз, что не сосчитать. Фактически, это универсальная функция, которая позволяет бороться с практически любыми проблемами, связанными с кодировками, поэтому запомните её, и если вдруг у Вас вместо русского текста выводится непонятно что, то подумайте об её использовании. А рисовать русский текст в PHP Вы уже умеете, с чем я Вас и поздравляю!
Копирование материалов разрешается только с указанием автора (Михаил Русаков) и индексируемой прямой ссылкой на сайт (http://myrusakov.ru)!
Добавляйтесь ко мне в друзья ВКонтакте: http://vk.com/myrusakov.
Если Вы хотите дать оценку мне и моей работе, то напишите её в моей группе: http://vk.com/rusakovmy.
Если Вы не хотите пропустить новые материалы на сайте,
то Вы можете подписаться на обновления: Подписаться на обновления
Если у Вас остались какие-либо вопросы, либо у Вас есть желание высказаться по поводу этой статьи, то Вы можете оставить свой комментарий внизу страницы.
Порекомендуйте эту статью друзьям:
Если Вам понравился сайт, то разместите ссылку на него (у себя на сайте, на форуме, в контакте):
Комментарии ( 2 ):
Прямоугольники вместо текста на русском.
Значит у Вас нет данного шрифта.
Для добавления комментариев надо войти в систему.
Если Вы ещё не зарегистрированы на сайте, то сначала зарегистрируйтесь.
Copyright © 2010-2021 Русаков Михаил Юрьевич. Все права защищены.
PHP. Кириллица в регулярных выражениях

Задача заключалась научить PHP обрабатывать в регулярный выражениях русские символы. решение нашлось не сразу, но оказалось довольно таки простым.
Перед регулярным выражением в скрипте следует указать локаль, делается это написанием следующей команды (если используется кодировка UTF-8, если CP1251 то пишем её):
далее само регулярное выражение с ключем \u, чтобы обработчик знал, что в вырожении используются национальные символы.
Таким образом мы научили регулярные выражения дружить с кириллицей. Если есть какие-то дополнения то пожалуйста пишите.
Похожие записи
4 комментария to “PHP. Кириллица в регулярных выражениях”
Не вырезает согласно шаблону прочие символы, типа знака вопроса и т.д. Если убрать ключ \u, то вырезает, но не дружит с кириллицей…
Разобрался. Ключ не там ставил
/[^a-zA-Z0-9а-яА-Я ]/u — верно
/[^a-zA-Z0-9а-яА-Я ]u/ — неверно
Была похожая задача с кириллицей, только на проверку русских символов в слове без цифр, то бишь слово должно быть написано ТОЛЬКО русскими буквами.
Писать через setlocale(LC_ALL, «ru_RU.UTF-8»); порой не вариант — не каждый сервак работает с кириллицей (как и в моем случае тоже). Поэтому решил обойти другим способом через 2 функции. Может кому то понадобится — буду рад
$arr = array(«А» => «A», «Б» => «B», «В» => «V», «Г» => «G», «Д» => «D»,
«Е» => «E», «Ё» => «YO», «Ж» => «ZH»,
«З» => «Z», «И» => «I», «Й» => «J», «К» => «K», «Л» => «L»,
«М» => «M», «Н» => «N», «О» => «O», «П» => «P», «Р» => «R»,
«С» => «S», «Т» => «T», «У» => «U», «Ф» => «F», «Х» => «X»,
«Ц» => «C», «Ч» => «CH», «Ш» => «SH», «Щ» => «SHH», «Ъ» => «‘»,
«Ы» => «Y», «Ь» => «», «Э» => «E», «Ю» => «YU», «Я» => «YA»,
«а» => «a», «б» => «b», «в» => «v», «г» => «g», «д» => «d»,
«е» => «e», «ё» => «yo», «ж» => «zh»,
«з» => «z», «и» => «i», «й» => «j», «к» => «k», «л» => «l»,
«м» => «m», «н» => «n», «о» => «o», «п» => «p», «р» => «r»,
«с» => «s», «т» => «t», «у» => «u», «ф» => «f», «х» => «x»,
«ц» => «c», «ч» => «ch», «ш» => «sh», «щ» => «shh», «ъ» => «»,
«ы» => «y», «ь» => «», «э» => «e», «ю» => «yu», «я» => «ya»,);
Соль в том, что кол-во замен должно равняться кол-ву символов в слове
А как через preg_match (исключительно через эту функцию) искать внутри файла кириллические слова?


