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

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

Кодировки сервера, файла и серверного скрипта (программы)

Кодировки… Вопрос, вроде бы, банальный, но, если набрать в поиске фразу типа «что такое кодировка html-документа», с одной стороны, Google, Яндекс выведут немало страниц, релевантных данному запросу. С другой стороны, внимательное прочтение многих статей заставляет сделать вывод: их авторы механически, толком не понимая, что делают, применяют те или иные кодировки. И, зачастую, достаточно успешно. Попробуем докопаться до истины, если не полностью, то хотя бы отчасти.

Проблема с кодировками может возникнуть, когда идет речь о национальных языках, которые состоят из нелатинских букв. Также может появиться необходимость в отображении на странице определенных «особенных» символов.

Известно, что в настоящее время универсальной, вроде бы, является кодировка UTF-8. Особых недостатков она, по идее, не имеет. Хотя, вот ее недостатки по сравнению с Windows-1251:

  1. Страница, выполненная в однобайтовой кодировке (например, в Windows-1251), будет открываться, как правило, быстрее – по причине меньшего объема занимаемой памяти и, соответственно, меньшей величины трафика: ведь в UTF-8 один символ может занимать от двух до… шести байт (в среднем, как правило, три байта, поэтому объем трафика будет, соответственно, в среднем, в 1,5 раза выше для русскоязычной вебстраницы в кодировке UTF-8 по сравнению с той же самой страницей в кодировке Windows-1251);
  2. Пишут, что… Юникод достаточно коварен и подвержен «атакам неправильной кодировкой». Кстати, с Windows-1251 - все проще: она является однобайтовой, поэтому подобная атака при ее использовании едва ли возможна.
  3. Строки, закодированные в кодировке UTF-8, недостаточно эффективно обрабатываются, например, регулярными выражениями.

Можно встретить следующие доводы, в пользу преимуществ от использования кодировки UTF-8:

  1. Многие серверы в интернете настроены на нее по умолчанию;
  2. Вебстраница отправляет данные именно в кодировке UTF-8 (точнее, это – одна из нескольких стандартных кодировок, в которых может отправляться сообщение) и, следовательно, именно в ней сообщение принимается сервером;
  3. Кодировка UTF-8 стандартно используется в операционных системах типа UNIX/Linux;
  4. Если браузер работает в НЕРУСИФИЦИРОВАННОЙ операционной системе Windows, то русскоязычные символы в кодировке Windows-1251 отображаться НЕ БУДУТ (или будут, но – неверно), в отличие от тех же символов, закодированных в UTF-8;
  5. Юникод включает практически все современные письменности, а также специальные, математические и некоторые иные символы;
  6. Если сайт выполнен на РНР, то UTF-8 – это одна из (довольно большого перечня) кодировок, которая может там использоваться; это упрощает разработку программ на РНР в силу отсутствия необходимости перекодировать строки;
  7. При необходимости поддержки других языков (например, одновременно – арабского, норвежского и т.д.) придется или использовать соответствующие этим языкам кодировки или одну – UTF-8 (впрочем, возможна UTF-16 и т.п.).

Видится, что наиболее существенным является довод из последнего пункта и, отчасти, второго. А именно – если планируется размещение, скажем, китайского, арабского и русского текста на одной вебстранице – тут едва ли получится обойтись одной лишь Windows-1251. Тогда как UTF-8 справится с данной задачей без особых проблем. А главное преимущество UTF-8 — не в расширении набора символов, а в простом способе их включения в документ.


Как будет вести себя сервер при разных кодировках?

Пусть на вебстранице есть форма, которая передает данные на сервер. Принимает эти данные программа, например, написанная на языке PHP.

Форма, как правило, передает данные в кодировке UTF-8, для чего они предварительно перекодируются javascript при помощи строчки вида

var data = encodeURIComponent(data);

При этом при создании AJAX-запроса необходимо указать вид кодировки:

xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');

В подавляющем большинстве случаев для AJAX-запросов используется именно такой подход. Это означает, что данные на сервер пойдут в кодировке UTF-8.

Соответственно, именно в такой кодировке они будут приняты программой (РНР). Если на сервере (точнее, на хостинге) установлена кодировка тоже UTF-8 – проблем меньше. Они возникают, если там присутствует другая кодировка, например, Windows-1251 (CP1251).

Кстати, виртуальный сервер Denwer по умолчанию настроен именно на Windows-1251. Заменить ее на UTF-8, при желании, можно, открыв файл

/usr/local/apache/conf/httpd.conf

найти там строчку

AddDefaultCharset windows-1251

и заменить ее на

AddDefaultCharset utf-8

Ну и, мосле этого – перезапустить Denwer.

От чего зависит кодировка, используемая РНР?

На самом деле, она там может быть РАЗНОЙ – в зависимости от того, ГДЕ применяется. Например, регулярные выражения кодируются в одной кодировке. Строки – в другой…

По умолчанию, кодировка строк, с которыми работает программа на PHP, используется та, в которой сохранен файл с программой. Посмотреть ее можно, открыв этот файл (с расширением php) в текстовом редакторе, например, в Notepad++. Внизу справа будет присутствовать наименование кодировки, например, ANSI as UTF.

Что означает UTF-8 без BOM?

Кликнув мышью на пункт «Кодировки», видим, в самом деле, что установлена кодировка UTF-8 без BOM

Кстати, что такое ВОМ?

Дело в том, что для определения формата представления Юникода в начало текстового файла записывается сигнатура — символ U+FEFF (неразрывный пробел с нулевой шириной), также именуемый маркером последовательности байтов (от английского слова byte order mark (BOM)). Это позволяет различать UTF-16LE и UTF-16BE, поскольку символа U+FFFE не существует. Также этот способ иногда применяется для обозначения формата UTF-8, хотя к этому формату и неприменимо понятие порядка байтов. Файлы, следующие этому соглашению, начинаются с таких последовательностей байтов:

UTF-8   -    EF BB BF
UTF-16BE   -    FE FF
UTF-16LE   -    FF FE
UTF-32BE   -    00 00 FE FF
UTF-32LE   -    FF FE 00 00

Таким образом, если подобные байты присутствуют в файле (увидеть в окне редактора их не получится), то Notepad++ может самостоятельно определить кодировку файла (внимание!), даже если там нет ничего вообще (т.е. файл «пустой»).

Если выбрать «Кодировать в UTF» (это означает UTF-8 с BOM), то надпись внизу справа окна редактора сменится на UTF-8. Это означает, что редактор сам определил тип кодировки файла по наличию тех самых байтов, задающих ВОМ.

Примечание. Следует различать в программе Notepad++ операции «Кодировать в…» от «Преобразовать в … ». Операция «Кодировать в…» лишь меняет характер отображения текста на экране редактора, не меняя самого файла, содержащегося на жестком диске (хотя, произведенные изменения можно сохранить, тогда файл на жестком диске перезапишется). Тогда как операция «Преобразовать в…» производит именно – перекодирование, т.е. преобразование самого файла.

Пример

Рассмотрим такой код на РНР:

<?php
// Определяем кодировку программы на РНР по умолчанию:
echo "Default coding: ". mb_internal_encoding().'<br />';
echo 'This is the regular expression coding: '. mb_regex_encoding () . "<br />";
echo "Soon we shall create file. Вскоре мы создадим файл.<br />";
// Устанавливаем кодировку в программе на РНР как UTF-8:
mb_internal_encoding("UTF-8");
// Определяем кодировку программы на РНР по умолчанию:
echo "Custom coding: ". mb_internal_encoding().'<br />';
echo 'This is the regular expression coding: '. mb_regex_encoding () . "<br />";
// Пытаемся создать файл под названием new_file в корневом каталоге сайта:
$input = @fopen($_SERVER['DOCUMENT_ROOT'] . '/new_file.html', "a+") or die('Невозможно создать или открыть файл.');
echo "The file is created. Файл создан.<br />";
?>

Запускаем этот файл в Denwer, вот что получается:

Default coding: ISO-8859-1
This is the regular expression coding: EUC-JP
The file is created. Файл создан.
Custom coding: UTF-8
This is the regular expression coding: EUC-JP
The file is created. Файл создан.

Видим, что:

  1. Вначале по умолчанию РНР использовал кодировку ISO-8859-1, хотя, вроде как, Notepad++ нам указывал на UTF. Кстати, если открыть этот файл в программе PHPStorm, внизу справа также будет указана кодировка UTF-8.
  2. После принудительного задания кодировки функцией mb_internal_encoding("UTF-8") она стала UTF-8.
  3. Регулярные выражения кодированы в совсем другой кодировке, а именно – в EUC-JP, причем – ВНЕ ЗАВИСИМОСТИ(!) от кодировки файла, в котором находится данная программа (на РНР).
  4. Русскоязычный текст отображается нечитаемо в обоих случаях.

Открыв созданный файл new_file.html, можно убедиться, что он создан, если верить Notepad++, в кодировке ANSI (что означает Windows-1251 в данном случае), являясь при этом пустым(!). Если же открыть его в программе PHPStorm, он смело показывает его кодировку, как UTF-8. М-да... Больше и сказать нечего.

А теперь будем экспериментировать

Изменим через Notepad++ (PHPStorm, вроде бы, не дает такой возможности, хотя и является платной IDE, в отличие от первого) кодировку с ANSI as UTF на UTF. Для этого кликнем «Кодировки», «Кодировать в UTF-8». Сохраняем файл. В браузере, после обновления страницы, видим:

Default coding: ISO-8859-1
This is the regular expression coding: EUC-JP
The file is created. Файл создан.
Custom coding: UTF-8
This is the regular expression coding: EUC-JP
The file is created. Файл создан.

Открываем файл new_file.html
в Notepad++ и в PHPStorm и видим, что кодировки, указываемые этими программами, не изменились. Кстати, в PHPStorm можно задать кодировку Windows-1251, при этом Notepad++ продолжит указывать все ту же ANSI.

Задаем кодировку Windows-1251 в метатеге вебстраницы

Для этой цели дополняем код немного:

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=windows-1251"/>
</head>
<body>
<p>Это просто абзац текста.</p><br />
<?php
// Определяем кодировку программы на РНР по умолчанию:
echo "Default coding: ". mb_internal_encoding().'<br />';
echo 'This is the regular expression coding: '. mb_regex_encoding () . "<br />";
echo "The file is created. Файл создан.<br />";
// Устанавливаем кодировку в программе на РНР как UTF-8:
mb_internal_encoding("UTF-8");
// Определяем кодировку программы на РНР по умолчанию:
echo "Custom coding: ". mb_internal_encoding().'<br />';
echo 'This is the regular expression coding: '. mb_regex_encoding () . "<br />";
// Пытаемся создать файл под названием new_file в корневом каталоге сайта:
$input = @fopen($_SERVER['DOCUMENT_ROOT'] . '/new_file.html', "a+") or die('Невозможно создать или открыть файл.');
echo "The file is created. Файл создан.<br />";
?>
</body>
</html>

Запускаем в браузере. Результаты – те же самые, что и в предыдущем случае. И именно, русский текст выводится читаемо только в том случае, когда указана кодировка (через Notepad++) UTF-8 (т.е. UTF-8 с ВОМ). Тогда как выбор UTF-8 без BOM приводит вновь к нечитаемым символам на месте русских букв. То же самое наблюдается и когда в метатеге задана UTF-8 вместо Windows-1251.

Выводы:

  1. Метатег html, задающий кодировку страницы как Windows-1251 или UTF-8, в данном случае не влияет на ее отображение браузером.
  2. На отображение русскоязычного текста влияет, в какой кодировке сохранена исходная страница. Причем, это имеет значение как для текста, который задан на самой странице (при помощи тега <p>), так и сформирован при помощи PHP.

А если файл будет иметь расширение html и не будет обрабатываться интерпретатором РНР?

В том смысле, что такой файл не будет обрабатываться интерпретатором РНР и загрузится локально, т.е. по протоколу file. Понятно, что при этом PHP-код будет отображаться в виде простого (отформатированного по умолчанию) текста в браузере.

При этом если в метатеге страницы указана кодировка UTF-8, нет разницы, сохранена ли страница в UTF-8 с BOM или без: в любом случае русский текст отображается читаемо. Т.е. наличие ВОМ здесь не играет роли.

А вот если на странице в метатеге задать кодировку Windows-1251, то корректно отображается она (страница) только в случае, когда в Notepad++ задать кодировку UTF-8BOM). Тогда как кодировка без BOM приводит к нечитаемому отображению русского текста.

Вот тебе бабушка и Юрьев день и, якобы, «бесполезность» кодировки UTF с ВОМ… для UTF-8, постулируемая Википедией и не только. Эту «бесполезность» почему-то любят постулировать также и на компьютерных форумах.

Вопрос, зачем и почему – оставим без внимания (Ю.Ю. Шевчук).

И еще: файлы, которые интерпретируются PHP, отображаются, в общем случае, иначе по сравнению со статическими файлами html – в смысле читаемости в случае несовпадения кодировок. Это и понятно: ведь на последние не влияют ни кодировка сервера, ни кодировка РНР.

А теперь изменим кодировку сервера

Открываем файл httpd.conf и меняем там, как уже говорилось, строчку AddDefaultCharset windows-1251 на AddDefaultCharset utf-8. Перезапускаем Denwer.

На файл, загруженный по протоколу file, конечно, никаких влияний не будет – все останется, как прежде.

А вот с файлом PHP – дело немного интереснее. Вне зависимости от того, как кодируется файл в кодировке UTF-8 с BOM или без, результат получается примерно такой:

Это просто абзац текста.
Default coding: ISO-8859-1
This is the regular expression coding: EUC-JP
The file is created. Файл создан.
Custom coding: UTF-8
This is the regular expression coding: EUC-JP
The file is created. Файл создан.

Текст отображается читаемо уже ВНЕ ЗАВИСИМОСТИ от того, какая кодировка указана в метатеге html: UTF-8 или Windows-1251, что видится логичным: коль скоро на сервере указана кодировка (по умолчанию) UTF-8, то наличие BOM, призванных различать разные типы UTF кодировок, получается, ни к чему: сервер и так знает про UTF-8. Более того, русский текст отображается в браузере читаемо, даже если файл с кодом РНР кодировать как ANSI: при этом русскоязычные символы, естественно, становятся нечитаемыми (будет, так сказать, абракадабра), но, в браузере все отображается, как полагается.

Далее, видим, что кодировка РНР по умолчанию осталась той же самой, что и ранее: ISO-8859-1. Т.е. это – вещь не зависящая от кодировки, установленной на сервере. Не изменилась и кодировка регулярных выражений в PHP.

Однако, файл new_file.html, создаваемый программой, судя по указанию Notepad++, каждый раз имеет кодировку ANSI (т.е. windows-1251), опять же, ВНЕ зависимости от того, какую кодировку указать в метатеге. Конечно, PHPStorm, как обычно, указывает для него кодировку UTF-8.

По всей видимости, тот факт, что файл всегда создается в ANSI, зависит, скорее, от операционной системы (Windows 7), чем от самого Denwer. Это тоже логично: ведь PHP, работающий под управлением Denwer, вроде как, пользуется для целей создания файлов «услугами» операционной системы, системным интерфейсом, направляя к нему соответствующие стандартные системные вызовы. А стандартная кодировка Windows – это Windows-1251.

Выводы

  1. Ну, во-первых, во избежание неточностей, целесообразно бы указывать кодировку (для строк) в самом начале программы РНР. Что не было потом, как говорится. Благо, это – несложно и делается одной строчкой. Например, для UTF-8 можно написать:

    mb_internal_encoding("UTF-8");

  1. Задание кодировки UTF-8 по умолчанию на виртуальном сервере делает текст в браузере читаемым независимо от того, в какой кодировке закодирован исходный файл PHP и независимо от кодировки, заданной в метатеге. Это справедливо, по крайней мере, для кодировок Windows-1251 и UTF-8.
  2. Кодировка файла ANSI as UTF (т.е. без ВОМ) может быть причиной нечитаемости русскоязычного текста в случае кодировки виртуального сервера Windows-1251 или при локальной загрузке страницы (при помощи протокола file), в том случае, когда в метатеге страницы кодировка задана как Windows-1251 или она вообще отсутствует. Иными словами, отсутствие BOM для файла, кодированного в UTF-8, может вызвать проблемы с отображением контента страницы.

Для наглядности, выводы сведены в таблицу:

Кодировка, заданная в метатеге страницы Кодировка файла, показываемая в Notepad++ Отображение файла html по протоколу file Отображение файла PHP при кодировке виртуального сервера
Windows-1251 UTF-8
- ANSI as UTF (UTF-8 без BOM) Нечитаемый Нечитаемый Читаемый
UTF-8 Читаемый Читаемый Читаемый
Windows-1251 ANSI as UTF (UTF-8 без BOM) Нечитаемый Нечитаемый Читаемый
UTF-8 Читаемый Читаемый Читаемый
UTF-8 ANSI as UTF (UTF-8 без BOM) Читаемый Нечитаемый Читаемый
UTF-8 Читаемый Читаемый Читаемый

Вот почему кодировка сервера UTF-8, в самом деле, видится более удобной, чем Windows-1251 – даже при использовании в операционной системе Windows (седьмой версии).

Как быть с русскоязычным текстом, формируемым на странице, отдаваемой сервером при помощи PHP?

Итак, если кодировкой сервера является UTF-8 – проблем меньше. Можно просто отдавать русскоязычный текст при помощи, например, команды echo. Если же кодировкой сервера является Windows-1251, то, на самом деле, особенно страшного ничего нет: надо лишь кодировать русскоязычный текст, отдаваемый РНР серверу, который он, в свою очередь, отдает браузеру. Если текст присутствует или формируется в самом файле РНР, то для этой цели наиболее целесообразна команда типа

mb_convert_encoding('Русскоязычный текст', "Windows-1251", "utf-8" );

Однако, бывают случаи, когда русскоязычный текст считывается из файла, например, базы данных. И вот здесь зависит от того, как он закодирован. Например, если в файле – кодировка ANSI (Windows-1251), то это означает, что перекодировать считываемый из него текст НЕ НАДО. Ибо он и так уже закодирован в нужной кодировке. Этот момент может привести, иной раз, к проблемам. Когда, к примеру, разные части баз данных записаны в разных кодировках (о чем свидетельствуют обсуждения на компьютерных форумах). Тем более, что повторное кодирование может привести к нечитаемости некоторых символов (в частности, кириллической буквы И) - даже при последующем обратном (тоже повторном!) перекодировании.


Комментарии:
Олег09.11.2019 22:47РедактироватьУдалить
Если речь о РНР, то есть еще кодировка для регулярных выражений. По умолчанию она не utf. Поэтому с кириллицей у функций типа preg_replace могут быть проблемы, если не указать кодировку.
Всего комментариев: 1
Пожалуйста, не забудьте ознакомиться с правилами оставления комментариев.



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

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

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