Хотя действительно можно вручную выбрать некоторую кодировку (и не забудьте отключить ее при посещении другого сайта), на самом деле веб-сайт должен был правильно ее указать. Либо сервер, либо сами веб-страницы должны что-то указывать, иначе все, что может сделать браузер, - это сделать предположение. И, конечно же , если задана кодировка, то HTML документ должен фактически использовать эту кодировку. Не так много для веб-сайта из вопроса, как показано ниже:
Чтобы увидеть, указал ли веб-сервер что-то, нужно взглянуть на так называемые заголовки. Используя онлайн-сервис от web-sniffer.net, вы сможете найти заголовки, которые вы получите:
HTTP/1.1 200 OK
Date: Mon, 17 Aug 2009 17:47:03 GMT
Server: Apache
Last-Modified: Mon, 27 Nov 2006 23:38:49 GMT
ETag: "758b0606-1a316-4234309151440"
Accept-Ranges: bytes
Content-Length: 107286
Connection: close
Content-Type: text/html; charset=utf-8 (BOM UTF-16, litte-endian)
Последняя строка кажется немного странной: как сервер может претендовать на то, чтобы быть как UTF-8, так и UTF-16? Значение для charset
должно быть одним из тех, которые зарегистрированы в IANA (например, UTF-8 без каких-либо комментариев). Однако использование анализатора пакетов Wireshark вместо онлайн-сервиса показывает, что текст (BOM UTF-16, litte-endian) фактически является комментарием от онлайн-сервиса, а не отправляется веб-сервером.
Итак: веб-сервер утверждает, что отправит нам HTML-документ в кодировке UTF-8.
Однако следующий HTML-документ неверен (отредактирован для удобства чтения):
ÿþ<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Lesson 5</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<link href="main.css" rel="stylesheet" type="text/css">
</head>
...
Выше строка, указывающая тип содержимого, должна появляться первой в <head>
, иначе браузер не будет знать, как обрабатывать специальные символы в <title>
. Что еще более важно, первые два нечетных символа ÿþ
на самом деле представляют собой шестнадцатеричные коды FF и FE, которые, как уже отмечалось в онлайн-сервисе, представляют собой метку порядка байтов для UTF-16, litte-endian.
Итак: веб-сервер пообещал отправить UTF-8, но затем отправил маркеры, которые указывали UTF-16 LE. Далее в HTML-документе утверждается, что он снова использует UTF-8.
Действительно, Wireshark показывает, что настоящий документ HTML имеет кодировку UTF-16. Это означает, что каждый символ отправляется с использованием не менее двух байтов (октетов). Как и 6 символов в <html>
, отправляются в виде 12 шестнадцатеричных байтов 3C 00 68 00 74 00 6D 00 6C 00 3E 00
. Тем не менее, этот самый веб-сайт вполне мог быть простым ASCII, так как он, похоже, вообще не использует символы, не входящие в ASCII. Вместо этого источник HTML полон числовых ссылок на символы (NCR), таких как:
यह दिल्ली
शहर है।
Браузер отображает вышеизложенное как यह दिल्ली शहर है।. Однако из-за использования NCR и UTF-16 одному символу य (Unicode U+092F) требуется до 14 байтов в 26 00 23 00 32 00 33 00 35 00 31 00 3B 00
, потому что он написан с использованием NCR य
в то время как 7 символов ASCII самого NCR кодируются с использованием UTF-16. Когда не используются NCR, в UTF-8 для этого одиночного require потребуется 3 байта (E0 A4 AF
), а в UTF-16 два байта (09 2F
).
Для этого источника HTML использование UTF-16 является полной тратой пропускной способности, и сервер также не использует сжатие.