Embora seja possível escolher manualmente alguma codificação (e não se esqueça de desativá-la quando visitar outro site), na verdade, o site deve especificá-la corretamente. O servidor ou as próprias páginas da Web devem especificar algo, pois, do contrário, tudo que o navegador pode fazer é fazer algumas suposições. E, claro, se uma codificação for especificada, o documento HTML deverá, de fato, usar essa codificação. Não tanto pelo site da questão, como mostrado abaixo:
Para ver se o servidor web especificou algo, é necessário olhar os chamados cabeçalhos . Usando o serviço online de web-sniffer.net para revelar os cabeçalhos que receberá:
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)
A última linha parece um pouco estranha: como o servidor pode reivindicar algo como UTF-8 e UTF-16? O valor para charset
deve ser um desses registrados com a IANA (por exemplo, UTF-8 sem algum comentário). No entanto, usar o sniffer de pacote Wireshark em vez do serviço online revela que o texto (BOM UTF-16, litte-endian) é, na verdade, um comentário do serviço online, não enviado pelo servidor da Web.
Então: o servidor web afirma que nos enviará um documento HTML codificado em UTF-8.
No entanto, o documento HTML a seguir está errado (editado para legibilidade):
ÿþ<!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>
...
Acima, a linha que especifica o tipo de conteúdo deve ser a primeira a aparecer dentro de <head>
, caso contrário, o navegador não saberá como manipular caracteres especiais no <title>
. Mais importante, os dois primeiros caracteres ímpares, ÿþ
, são na verdade os códigos hexadecimais FF e FE, que, como o serviço online já mencionado, é o Byte-Order Mark para UTF-16, litte-endian.
Então: o servidor web prometeu enviar UTF-8, mas depois enviou marcadores que indicavam UTF-16 LE. Em seguida, no documento HTML, ele afirma estar usando o UTF-8 novamente.
De fato, o Wireshark mostra que o documento HTML real é codificado em UTF-16. Isto implica que cada caractere é enviado usando pelo menos dois bytes (octetos). Como os 6 caracteres em <html>
são enviados como os 12 bytes hexadecimais 3C 00 68 00 74 00 6D 00 6C 00 3E 00
. No entanto, este site poderia muito bem ter sido simples ASCII, pois não parece usar nenhum caractere ASCII. Em vez disso, a fonte HTML está cheia de referências de caracteres numéricos ( NCRs ), como:
यह दिल्ली
शहर है।
Um navegador exibe o acima como यह दिल्ली शहर है ।. No entanto, devido ao uso de NCRs e UTF-16, o caractere único य ( Unicode U + 092F ) requer até 14 bytes em 26 00 23 00 32 00 33 00 35 00 31 00 3B 00
, porque é escrito usando NCR य
enquanto os 7 caracteres ASCII da própria NCR são codificados usando UTF-16. Quando não estiver usando NCRs, em UTF-8 este único य precisaria de 3 bytes ( E0 A4 AF
), e em UTF-16 dois bytes ( 09 2F
).
Para essa fonte HTML usando UTF-16 é um desperdício total de largura de banda, e o servidor também não está usando nenhuma compactação.