Научный консалтинг
Главная
Контакты
Номер телефона
Как мы работаем
Гарантии
Условия
Цены

Последнее обновление:

Почему заглавная буква И иногда кодируется с ошибкой?

Что такое кодировка и для чего она используется в вебпрограммировании, объяснять не будем. Надеемся, практически каждый разработчик сайтов сталкивался с необходимостью применения кодирования.

Если символы текста (например, html_кода) принадлежат латинскому алфавиту или являются символами в прямом смысле этого слова, например, представляют собой точку, запятую, восклицательный или вопросительный знаки и т.п., то проблем с ними, как правило, не возникает. А вот с алфавитом другого языка, например, русского, могут возникнуть непредвиденные проблемы.

Поговорим об одной из ошибок, которая может встретиться при кодировании из кодировки Windows-1251 в кодировку UTF-8 или обратно.

Речь идет об ошибке, которую иной раз очень трудно «выловить», так как она, фактически, ЕДИНСТВЕННАЯ. И касается она только заглавной буквы И.

Как известно, язык РНР работает с данными в кодировке UTF-8. Тогда как на вебстранице может быть, вообще говоря, любая кодировка, например, Windows-1251. Соответственно, если данные переданы с этой вебстраницы (например, путем технологии AJAX), то их следует перекодировать в UTF-8, например, при помощи команды:

$data = mb_convert_encoding($data, "utf-8", "cp1251");

Если же необходимо записать данные в файл, который будет открываться в кодировке Windows-1251, то целесообразно осуществить обратную процедуру перекодировки. Кроме того, чтобы вывести русский текст при помощи РНР, опять-таки, необходимо также его вначале перекодировать в Windows-1251, иначе возникнут нечитаемые символы типа если СѓРєР°

Многие находят такие процедуры утомительными (от некоторых программистов, мнящих себя специалистами, я даже слышал, что это, мол, очередная «головная боль»), поэтому принимают решение ВЕЗДЕ использовать универсальную кодировку, коей и является UTF-8.

Конечно, подобный подход может являться целесообразным. Но, если по каким-то причинам невозможно или попросту не хочется его применять? Например, если изначально сайт создавался в другой кодировке, т.е. не в UTF-8? В самом деле, не переделывать же весь сайт только по причине сложности работы с кодировками.

Проблемы с заглавной буквой И

Проблема может возникнуть в ситуации, когда по ошибке или недосмотру кодирование в UTF-8 (или, наоборот, из нее) было сделано ПОДРЯД более одного раза.

Самое интересное, что все другие буквы русского алфавита, как строчные, так и прописные (заглавные) без проблем проходят процедуру двойного кодирования и UTF-8 и, соответственно, двойного декодирования из нее. Но, только не заглавная буква И.

Чтобы убедиться в этом, мы создали небольшой РНР-код, который демонстрирует приведенные выше рассуждения. Вот, кстати, этот код - см. ниже.

Заранее соглашусь, что код неоптимизированный. Ибо создавался на скорую руку - лишь с целью демонстрации ситуации.

Исходный код программы

<?php

$str1 = "0123456789АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдеёжзийклмнопрстуфхцчшщъыьэюя";

$str2 ="`~!@#$%^&*()_+-=;%:[]{}.,<>\|;:


?";

$str3 = "!№;%:?*()_-+=.,\/";

$str4 = "qwertyuiop[]asdfghjklzxcvbnmQWERTYUIOP{}ASDFGHJKL:ZXCVBNM";

$str5 = "/*-789+4561230.

";


echo mb_convert_encoding("КИРИЛЛИЦА<br/>", "Windows-1251", "UTF-8");

coder($str1);

echo mb_convert_encoding("<hr/><br/>СИМВОЛЫ ЛАТИНСКИЕ<br/>", "Windows-1251", "UTF-8");

coder($str2);

echo mb_convert_encoding("<hr/><br/>СИМВОЛЫ, НАПЕЧАТАННЫЕ ПРИ ВКЛЮЧЕННОЙ (НА КЛАВИАТУРЕ) КИРИЛЛИЦЕ<br/>", "Windows-1251", "UTF-8");

coder($str3);

echo mb_convert_encoding("<hr/><br/>ЛАТИНСКИЕ БУКВЫ<br/>", "Windows-1251", "UTF-8");

coder($str4);

echo mb_convert_encoding("<hr/><br/>СИМВОЛЫ С ПРАВОЙ КЛАВИАТУРЫ<br/>", "Windows-1251", "UTF-8");

coder($str5);


function coder($str_i) {

echo mb_convert_encoding("Кодирования не было сделано:<br/>", "Windows-1251", "UTF-8");

print_letters($str_i);


$str_i = mb_convert_encoding($str_i, "Windows-1251", "UTF-8");

echo "<br/><br/>".mb_convert_encoding("Перекодировано в Windows-1251:<br/>", "Windows-1251", "UTF-8");

print_letters($str_i);


$str_i = mb_convert_encoding($str_i, "UTF-8", "Windows-1251");

echo "<br/><br/>".mb_convert_encoding("Перекодировано обратно, т.е. из  Windows-1251 в UTF-8:<br/>", "Windows-1251", "UTF-8");

print_letters($str_i);


$str_i = mb_convert_encoding($str_i, "UTF-8", "Windows-1251");

echo "<br/><br/>".mb_convert_encoding("ЕЩЕ РАЗ перекодировано в UTF-8:<br/>", "Windows-1251", "UTF-8");

print_letters($str_i);


$str_i = mb_convert_encoding($str_i, "Windows-1251", "UTF-8");

echo "<br/><br/>".mb_convert_encoding("Перекодируем обратно в Windows-1251 один раз:<br/>", "Windows-1251", "UTF-8");

print_letters($str_i);


$str_i = mb_convert_encoding($str_i, "Windows-1251", "UTF-8");

echo "<br/><br/>".mb_convert_encoding("Перекодируем обратно в Windows-1251 еще раз:<br/>", "Windows-1251", "UTF-8");

print_letters($str_i);

}


function print_letters($str){

   $str_length = strlen($str);

   for($i=1; $i<=$str_length; $i++) {

   $subString = substr($str, $i, 1);

   echo $subString.'<span style="background-color:blue"> </span>';

   }

}

?>

Запустить код и посмотреть результат можно на этой странице.

На что стоит обратить внимание?

Мы использовали все символы (как русские, так и латинские), которые можно ввести с типичной клавиатуры в операционной системе Windows. Конечно, символы, которых на клавиатуре нет и которые вводятся путем нажатия комбинации (одной или нескольких) функциональных клавиш мы здесь не рассматриваем.

Для наглядности, каждый символ отделен от соседних – пробелами, окрашенными в синий цвет.

Итак, что видим? Без кодирования русскоязычные символы отображаются в виде «абракадабры», что и следовало ожидать, ибо кодировка исходного документа, содержащего код РНР (ANSI как UTF-8 без BOM) и кодировка браузера, которая установлена на странице и автоматически определена браузером (т.е. кодировка Windows-1251) не совпадают.

Кодировка браузера установлена метатегом:

<meta http-equiv="Content-Type" content="text/html; charset=windows-1251"/>

Этот метатег присутствует в исходном коде просматриваемой Вами страницы.

После кодирования русских букв в Windows-1251 мы видим, что они, наконец, становятся читаемыми. Перекодировка обратно в UTF-8 дает ту же «абракадабру».

Теперь попробуем ЕЩЕ РАЗ перекодировать в UTF-8. Понятно, что опять «абракадарба», только другая. Вроде бы, ничего такого плохого не сделали? Подумаешь, мол, потом исправим ошибку, дважды перекодируем обратно – и делов-то, мол… Но, не так все просто.

Итак, ДВАЖДЫ перекодируем то, что получилось, ОБРАТНО в Windows-1251. И видим, что почти все хорошо, буквы вновь читаемые, за исключением заглавной буквы И. Которая почему-то стала теперь отображаться в виде знака вопроса (?).

Причем, при использовании виртуального сервера Denwer получался ОДИН знак вопроса, а на нашем хостинге - ДВА.

Повторимся, что со всеми остальными буквами и символами типичной клавиатуры, которые можно с нее ввести, ситуация иная: все они выдержали двойное перекодирования и являются читаемыми.

Ошибка двойной перекодировки заглавной буквы И – не повод отказываться от кодировки Windows-1251

Таким образом, можно видеть, что если применять кодировку только один раз, то все будет хорошо, никаких ошибок не возникает. А вот если более одного раза, то ошибки точно будут. По крайней мере, это касается заглавной буквы И. Если же перекодировать на дважды, а трижды, четырежды и т.д., то, вполне возможно, что подобные ошибки будут возникать и с другими русскими (кириллическими) буквами.

Кодирование и шифрование

Это стоит иметь в виду тем, кто решит использовать множественное перекодирование, например, в качестве простого средства шифрования. С одной стороны, вроде бы – сравнительно простой способ зашифровки необходимой русскоязычной информации. Ведь распознать кодировку правильно можно далеко не всегда – хоть вручную, хоть автоматически. С другой стороны, при этом будут возникать достаточно неочевидные ошибки. Так что, все же, лучше уж md5 или что-то подобное.

И, последнее. При написании этой статьи была сделана попытка оформить совокупности символов, подлежащих (пере)кодировке, в формате кода, с использованием тегов <code>. Идея, может быть, и хорошая, но успехом она не увенчалась: некоторые символы из «абракадабры» стали выглядеть, как пробелы. Поэтому пришлось оставить все, как есть, т.е. стандартное форматирование браузера.

Итог такой

Применение кодировки Windows-1251 особой помехой при разработке РНР-кода не является. Просто следует быть внимательным и не допускать ситуации многократного кодирования в одну и ту же кодировку без предварительного «возврата» в предыдущую.

Самое интересное, что ни в интернете, ни в серьезных книгах об этом информации нет. По крайней мере, автору статьи найти ее не удалось.

Комментарии:
Вячеслав15.03.2019 14:47
У нас такая ситуация что, на 1 серваке есть такая проблема при 1 перекодировке а на другом нет такой проблемы. Вот думаем что делать. Статья хорошая автору респект, сайт как будто вернулся в 90 года ))))
Научный Консалтинг15.03.2019 15:10
Вячеслав, у Вас на серверах стоит одинаковая версия РНР? Какая именно?
Кирилл19.07.2019 23:17РедактироватьУдалить
Like
Всего комментариев: 3
Пожалуйста, не забудьте ознакомиться с правилами оставления комментариев.



Подписаться на комментарии на этой странице

Мы можем выполнить

Другие услуги
Интересная и полезная
информация