Sie sind auf Seite 1von 8

O Mínimo Absoluto que Todo Desenvolvedor de

Software Deve Absolutamente, Positivamente


Saber Sobre Unicode e Conjunto de Caracteres
(Sem Desculpas!)

Por Joel Spolsky da Fog Creek Software

Há muita gente que se pergunta o que são aquelas misteriosas tags “Content-Type”. Sabe, aquelas
que aparecem no HTML e ninguém sabe o que significam?
Quem já não recebeu um e-mail de seus amigos da Bulgária em que a linha de assunto é “????
?????? ??? ????”?
Fico desanimado quando descubro quantos desenvolvedores de software
nada entendem de conjuntos de caracteres, codificação, nem de Unicode.
Há alguns anos, um testador beta imaginava se o FogBugz poderia tratar e-
mails vindo do Japão. Japonês? E existe e-mail em japonês? Eu não sabia.
Ao olhar mais detidamente os controles ActiveX que adquirimos no
mercado e que usávamos para analisar conteúdo MIME de e-mails,
descobri que eles tratavam de forma completamente errada os conjuntos de
caracteres, por isso tínhamos que escrever códigos heróicos para desfazer as
conversões erradas e refazê-las corretamente. Quando investiguei outra
biblioteca comercial, esta, também, possuía uma implementação do conjunto de caracteres
completamente sem nexo. Contatei o desenvolvedor desta biblioteca e ele meio que disse que “não
poderia fazer nada”. Como muitos programadores, ele desejava que o problema, de alguma forma,
sumisse, fosse varrido para debaixo do tapete.
Mas, não, não sumia. Quando descobri que a ferramenta PHP de desenvolvimento para web era
quase completamente ignorante dos problemas de codificação de caracteres e fazia uso
irresponsável de 8 bits por caractere, o que tornava quase impossível desenvolver aplicações web
adequadas ao uso internacional, pensei, basta!
Pois é, tenho que anunciar: se o leitor é um programador que não sabe o básico de caracteres,
conjunto de caracteres, codificação e Unicode e eu o pegar, vou castigá-lo e fazê-lo descascar
cebolas por 6 meses num submarino. Juro.
E mais uma coisa:

NÃO É TÃO DIFÍCIL

Neste artigo eu vou explicar exatamente o que todo programador deve saber. Todas aquelas coisas
sobre "plain text = ascii = caracteres são 8 bits" não estão apenas erradas, estão totalmente erradas e
quem ainda programa dessa maneira, não é muito melhor do que um médico que não acredita em
germes. Por favor, não escreva nenhuma linha de código até terminar de ler este artigo.
Antes de começar, devo avisar que se o leitor é uma daquelas raras pessoas que entende de
internacionalização, vai achar simples demais o que digo. Estou somente tentando estabelecer uma
base mínima, de modo que todos possam entender o que acontece e escrever códigos que tenham
pelo menos alguma possibilidade de funcionar com texto em outras línguas que não o subconjunto
do inglês sem palavras com acentos. Devo alertar que isso é apenas uma pequena parte do trabalho
de criar software para o mercado mundial. Como só posso escrever sobre um tópico de cada vez,
então hoje é sobre conjuntos de caracteres.

Uma Perspectiva Histórica

O jeito mais fácil de entender essas coisas é ir cronologicamente.


O leitor provavelmente está pensando que vou falar sobre antigos conjuntos de caracteres como
EBCDIC. Bem, não vou! EBCDIC não é relevante para a sua vida. Não temos de ir tão longe no
passado.
Outrora nos quase-antigos dias, quando Brian Kernighan e Dennis Ritchie trabalhavam na invenção
do Unix e escreviam o livro “C: a Linguagem de
Programação”, tudo era muito simples. EBCDIC caía
em desuso. Os únicos caracteres que interessavam eram
as letras sem acento do bom e velho inglês e existia um
código para elas, denominado ASCII, que podia
representar cada uma destas letras por números entre 32
e 127. O espaço era 32, a letra “A” era 65 e assim por
diante. Isto podia ser convenientemente gravado em 7
bits. Naquela época a maioria dos computadores era de
bytes de 8 bits, assim, podia-se representar todos os possíveis caracteres ASCII e ainda sobrava um
bit inteiro, que, se o programador fosse malvado, podia ser usado para propósitos inconfessáveis: os
ingênuos do WordStar usaram o bit mais alto para indicar a última letra de uma palavra. Isto
condenou o WordStar a ser um processador de texto que servia apenas para a língua inglesa.
Códigos abaixo de 32 eram chamados não-imprimíveis e eram usados para xingamentos.
Brincadeirinha. Eles eram usados como caracteres de controle, o 7 fazia seu computador apitar e o
12 fazia com que a página corrente fosse cuspida da impressora e uma nova fosse alimentada.
E tudo estava bem, desde que se falasse inglês.
Já que os bytes tinham espaço para até oito bits, um bocado de gente começou a pensar: “caramba,
posso usar os códigos 128 a 255 do jeito que quiser.” O problema foi que muita gente teve a mesma
idéia ao mesmo tempo e cada um teve suas próprias idéias do que colocar naquele espaço. O IBM-
PC tinha algo que era conhecido como o conjunto de caracteres OEM (Original Equipment
Manufacturer) que fornecia alguns caracteres
acentuados das línguas européias e uma porção de
caracteres para desenhar linhas...barras horizontais,
barras verticais, barras horizontais com pequenos
enfeites no lado direito, etc. e podiam-se usar estes
caracteres no desenho de lindas caixas e linhas na tela,
ainda se pode vê-las nos computadores 8088 das
secadoras de roupa das lavanderias. Na realidade, assim
que as pessoas começaram a comprar PCs fora dos
Estados Unidos, começou a pipocar todo tipo diferente
de conjuntos de caracteres OEM, que usavam, cada um
a seu modo, os 128 caracteres restantes. Por exemplo,
em alguns PCs o código 130 aparecia como “é”(sem as aspas), mas nos computadores vendidos em
Israel aparecia a terceira letra do alfabeto hebreu , oguimel (‫)ג‬, deste modo quando os americanos
enviavam seus “résumés” para Israel eles chegavam como “r‫ג‬sum‫ג‬s.” Em muitos casos, como na
Rússia, houve um monte de idéias do que fazer com os 128 caracteres superiores, com isto não
havia como intercambiar, de forma confiável, documentos com os russos.
Ao fim e ao cabo, esta situação foi codificada no padrão ANSI. Nesse padrão todos concordaram
com o que fazer abaixo de 128 era essencialmente o que tinha sido padronizado em ASCII, mas
havia diferentes formas de lidar com os caracteres do 128 para cima, dependendo de onde se vivia.
Esses sistemas diferentes foram denominados página de código. Por exemplo, em Israel usava-se o
código de página 862, já os gregos usavam o 737. Todos eram iguais abaixo de 128, mas diferentes
do 128 para cima onde todas as letras engraçadas residiam. As versões nacionais do MS-DOS
tinham dezenas destes códigos de página, que lidavam com qualquer coisa desde o inglês até ao
islandês e havia até alguns códigos de página multilíngüe que podiam lidar com o esperanto e o
galego no mesmo computador! Uau! Mas ter, digamos, hebreu e grego na mesma máquina era uma
impossibilidade completa a menos que o interessado escrevesse seu próprio software para exibi-los
como gráficos bitmap, pois hebreu e grego precisavam de códigos de página com interpretações
diferentes dos valores altos.
Enquanto isso, na Ásia, coisas mais estranhas ainda aconteciam para lidar com o fato de que os
alfabetos asiáticos têm milhares de letras, que não cabem em 8 bits. A forma de resolver isto era
através do uso de um sistema confuso chamado DBCS, o “double byte character set” no qual
algumas letras eram armazenadas em um byte e outras em dois. Era fácil mover-se para frente numa
seqüência de caracteres, mas próximo do impossível mover-se para trás. Os programadores eram
estimulados a não usar s++ e s-- para se movimentar para trás e para frente, mas sim usar funções
tais como AnsiNext e AnsiPrev do Windows que sabiam como lidar com aquela confusão toda.
Mas, ainda assim, a maioria das pessoas fazia de conta que um byte era um caractere e um caractere
eram 8 bits e desde que jamais se transportaria uma seqüência de caracteres de um computador para
outro ou se falaria mais de uma língua, isto sempre funcionava. Foi só a Internet aparecer que ficou
comum uma seqüência de caracteres ser passada de um computador para outro e a construção
começou a desmoronar. Por sorte inventaram o Unicode.

Unicode

O Unicode foi um imenso esforço para criar um conjunto único de caracteres que incluísse todos os
sistemas de escrita do planeta e até mesmo alguns de ficção como klingon. Algumas pessoas
cometem erro quando pensam que o Unicode é simplesmente um código de 16-bits onde cada
caractere ocupa 16 bits e assim podem existir 65.536 caracteres possíveis. Na realidade, isto não é
verdade. Este é o mais comum dos mitos sobre o Unicode, por isso ninguém precisa se sentir mal
se pensava assim.
De fato, o Unicode possui uma forma diferente de encarar os caracteres, os programadores têm que
entender esta forma do Unicode tratar os caracteres ou nada vai fazer sentido.
Até agora assumimos que uma letra é mapeada para alguns bits que podem ser guardados em disco
ou memória:
A -> 0100 0001
No Unicode uma letra é mapeada para um negócio chamado ponto de código que é apenas um
conceito teórico. Como este ponto de código é representado em memória ou disco já é outra estória.
Em Unicode a letra A é um ideal platônico. Ela simplesmente flutua no céu:

A
EsteA platônico é diferente do B a
e diferente do , mas é o mesmo que A A e e A. A idéia
que A na fonte Times New Roman é o mesmo caractere que o A na fonte Helvetica, mas diferente do
“a” minúsculo, isto não parece muito controverso, mas em algumas línguas entender o que é uma
letra pode ser controverso. A letra alemã ß é uma letra de verdade ou apenas uma forma elegante de
escrever ss? Se a forma da letra muda no fim da palavra, ela se torna uma letra diferente? Em
hebreu sim, em árabe não. O pessoal do consórcio Unicode elaborou o assunto por quase toda
década passada, houve um intenso debate político e, por isso, o leitor não precisa mais se preocupar.
O assunto já foi resolvido.
A cada letra platônica em cada alfabeto foi associado, pelo consórcio Unicode, um número mágico
que é escrito como: U+0639. Este número mágico é conhecido como um ponto de código. O U+
quer dizer “Unicode” e os números são hexadecimais. U+0639 é a letra arábica “Ain”. A letra A do
inglês é U+0041. No web site do Unicode ou com o utilitário charmap do Windows 2000/XP pode-
se ver todos os códigos e letras associadas.
Não há qualquer limite ao número de letras que o Unicode pode definir e de fato o consórcio foi
além do limite de 65.536, assim nem toda letra do Unicode pode ser representada por dois bytes,
mas, como já disse, isto era um mito.
Vamos lá, a seguinte seqüência:
Hello
seria representada em Unicode pelos cinco pontos de código:
U+0048 U+0065 U+006C U+006C U+006F.
Isto é somente uma porção de pontos de código. Na realidade, números. Nada foi dito ainda sobre
como armazenar estes números na memória nem como representá-los num e-mail.

Codificações

Agora é que as codificações aparecem.


A primeira idéia para a codificação Unicode, que gerou o mito sobre os dois bytes, foi, ei! vamos
armazenar estes números em dois bytes cada. E aí Hello se torna:
00 48 00 65 00 6C 00 6C 00 6F
Certo? Bem, nem tanto! Não poderia ser também:
48 00 65 00 6C 00 6C 00 6F 00 ?
Tecnicamente, sim, acredito que poderia, e, de fato, os primeiros implementadores desejavam ter a
capacidade de armazenar seus pontos de código Unicode no modo big-endian ou little-endian,
dependendo de qual deles possibilitava a maior rapidez ao seu particular CPU e, veja só, passou a
manhã e foi-se a noite e já existiam duas formas de armazenar o Unicode. Foi por isso que apareceu
a convenção bizarra de armazenar um FE FF no início de cada seqüência Unicode; a isto deu-se o
nome de Marca de Ordem de Byte do Unicode e se trocarmos os bytes altos pelos baixos a
seqüência fica FF FE e quem ler a seqüência vai saber que tem de permutar, alternadamente, cada
byte. Eca! Nem toda seqüência Unicode possui uma marca de ordem de byte no seu começo.
Por um instante pareceu que isso seria suficiente, mas os programadores reclamavam. “Veja todos
estes zeros!” diziam, pois, eram norte-americanos e viam texto em inglês que raramente utilizava
pontos de código acima de U+00FF. Também, eles eram hippies liberais da Califórnia que queriam
economizar (desprezo). Se fossem texanos não se incomodariam de beber duas vezes o número de
bytes. Mas os californianos, mais fracotes, não suportavam a idéia de dobrar o tamanho da memória
necessária para as seqüências, e, de qualquer modo, havia todos aqueles malditos documentos que
usavam os conjuntos de caracteres ANSI e DBCS e quem é que iria convertê-los? Moi? Por isso é
que se ignorou o Unicode por vários anos e com o passar do tempo as coisas pioraram.
Aí inventaram o conceito brilhante do UTF-8 que era outro sistema de armazenamento de
seqüências de pontos de código Unicode, aqueles números mágicos U+, na memória em bytes de 8
bits. Em UTF-8 cada ponto de código de 0 a 127 é armazenado em um único byte. Só os pontos de
código 128 e além são armazenados em 2, 3 e, na realidade, até 6 bytes.

Isso resultou no elegante efeito de os textos em inglês terem exatamente a mesma aparência em
UTF-8 ou em ASCII, com isto os americanos nem notaram que havia algo errado. Só o resto do
mundo é que tinha que dançar o miudinho. Por exemplo, Hello, que era U+0048 U+0065 U+006C
U+006C U+006F, seria armazenado como 48 65 6C 6C 6F, o que, pasmem! era o mesmo tanto em
ASCII quanto em ANSI e em todos conjuntos de caracteres OEM do planeta. Agora, se precisasse
usar letras acentuadas ou gregas ou klingon, seria necessário usar vários bytes para armazenar um
único ponto de código, mas os americanos não notariam. (Uma propriedade adicional do UTF-8 é
que os velhos códigos processadores de cadeias de caracteres que usam um único byte 0 como
terminador nulo não truncam as cadeias).
Até aqui expliquei três formas de codificação Unicode. O método tradicional de codificação em
dois bytes conhecido como UCS-2 (porque usa dois bytes) ou UTF-16 (porque usa 16 bits) e ainda
temos que decidir se é UCS-2 big-endian ou UCS-2 little-endian. Temos também o novo padrão
popular UTF-8 com a elegante propriedade de funcionar bem se por uma feliz coincidência a pessoa
trabalhar com texto em inglês e programas idiotas que não sabem que existe outra coisa além do
ASCII.
Há uma porção de outras formas de codificação para o Unicode. Há um negócio chamado UTF-7,
que se parece com o UTF-8, mas garante que o bit mais alto vai ser sempre zero, pois, se seus e-
mails Unicode precisassem passar por algum tipo de sistema de guarda de fronteira draconiana que
ache que 7 bits são mais do que suficientes, ainda podem se infiltrar e saírem ilesos. Há o UCS-4,
que guarda cada ponto de código em 4 bytes, o que propicia o divino atributo de garantir que todos
pontos de código podem ser armazenados no mesmo número de bytes, mas, Deus do céu, nem os
texanos seriam tão afoitos a ponto de gastar tanta memória.
E agora, já acostumados a pensar em termos das letras platônicas ideais representadas pelos códigos
de ponto Unicode, afirmo que esses códigos de ponto Unicode podem ser codificados em qualquer
esquema de codificação antigo! Por exemplo, podemos codificar a seqüência para Hello (U+0048
U+0065 U+006C U+006C U+006F) em ASCII ou na antiga codificação OEM do grego ou na
codificação ANSI do hebreu ou qualquer um das centenas de codificações que foram inventadas até
hoje, com uma pegadinha: algumas letras podem não ser mostradas! Se não houver um equivalente
para o código de ponto Unicode que queremos representar na codificação que usaremos, vamos
conseguir apenas um ponto de interrogação: ? Ou, se trabalharmos bem, uma caixa. Qual apareceu?
->
Há centenas de codificações tradicionais que armazenam corretamente somente alguns códigos de
ponto, e trocam todos os outros códigos de ponto para pontos de interrogação. Algumas
codificações populares de textos em inglês são Windows-1252 (o padrão do Windows 9x para as
línguas da Europa Ocidental) e o ISO-8859-1, também conhecido como Latin-1 (útil também para
as línguas da Europa Ocidental). Mas se tentarmos armazenar as letras russas ou hebréias nestes
esquemas de codificação, vamos conseguir um monte de pontos de interrogação. Os UTF 7, 8, 16 e
32 têm, todos, a capacidade de armazenar corretamente qualquer ponto de código.

O Fato Mais Importante Sobre Codificação

Se esquecer tudo sobre que falamos acima, lembre pelo menos um fato importante. Não faz sentido
uma seqüência de caracteres sem se saber que codificação ela utiliza. Não podemos mais enfiar
a cara na areia e achar que texto “puro” é ASCII.

Não Existe Este Tal de Texto Puro

Se tivermos uma seqüência de caracteres na memória, num arquivo ou num e-mail, temos que saber
que codificação usa ou não poderemos interpretá-lo ou mostrá-lo corretamente no monitor.
Quase toda afirmação estúpida como “minha página na Internet aparece como lixo” ou “ela não
consegue ler meus e-mails quando uso acentos” pode ser atribuída a um programador ingênuo que
não entendeu ainda que se ele não disser que uma certa cadeia de caracteres foi codificada em UTF-
8 ou ASCII ou isso 8859-1 (Latin 1) ou Windows 1252 (europeu ocidental), não se conseguirá
exibi-la corretamente ou mesmo entender onde ela termina. Há mais de uma centena de
codificações acima do código de ponto 127, uma pequena bobagem muda tudo.
Como se guarda a informação sobre qual codificação uma cadeia de caracteres usa? Bem, há uma
forma padrão de fazer isto. Num e-mail espera-se que contenha uma certa cadeia no seu cabeçalho
no formato
Content-Type: text/plain; charset="UTF-8"

Para uma página na Internet, a idéia original era que os servidores web enviariam um cabeçalho http
similar ao Content-Type junto com a página web -- não no corpo HTML, mas como um dos
cabeçalhos de resposta enviados antes da página HTML.
Isto causava problemas. Suponha-se que um grande servidor web com muitos sítios e centenas de
páginas criadas por muitas pessoas em muitas e diferentes línguas e com qualquer codificação que a
versão pessoal do Microsoft FrontPage fosse capaz de produzir. O servidor web por si só não
saberia em que codificação cada arquivo fora escrito, então, não poderia enviar o cabeçalho
Content-Type.
Seria conveniente colocar o cabeçalho Content-Type do arquivo HTML no próprio arquivo HTML,
com algum tag especial. Claro isto enlouqueceu os puristas... como se faria para ler o arquivo
HTML sem saber que codificação ele usava?! Afortunadamente, quase toda codificação em uso
trata do mesmo modo os caracteres entre 32 e 127, assim podemos iniciar a página HTML sem
utilizar as letras engraçadas:
<html>, <head>, <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
Mas esta meta-tag tem que ser a primeira coisa da seção <head>, pois, assim que o navegador web
encontra esta tag pára de analisar a página e reinicia, depois de reinterpretar toda página, com a
codificação especificada.
O que fazem os navegadores se não encontram um Content-Type no cabeçalho http nem na meta-
tag? O Internet Explorer age de forma muito interessante: tenta adivinhar, baseado na freqüência de
aparição dos diversos bytes em textos típicos codificados em várias línguas, que língua e
codificação foram usadas. Como os diversos códigos de página de 8 bits tendem a colocar as letras
nacionais em intervalos diferentes entre 128 e 255 e, como, cada língua tem histogramas de uso de
letras com características diferentes, este método tem uma boa probabilidade de funcionar. É muito
bizarro, mas, parece funcionar com tal freqüência que desenvolvedores ingênuos, que nunca
souberam que o navegador procuraria por um cabeçalho Content-Type na sua página, viam que sua
página aparecia OK no seu navegador e, então, estava tudo bem, até que um dia, escreviam algo que
não se conformava à freqüência de distribuição de uso de letras de sua língua nativa, então, o
Internet Explorer decidia que a língua era o coreano e exibia a página nesta língua, isto provaria,
pensava eu, que a Lei de Postel: “seja conservador com o que você emite e liberal no que você
aceita” não é um bom princípio de Engenharia. De qualquer modo, o que poderia fazer o pobre
leitor daquela página web, escrita em búlgaro, mas que era exibida em coreano (e nem mesmo um
coreano puro)? Usar o menu Exibir | Codificação e tentar algumas codificações (há pelo menos uma
dúzia para as línguas da Europa Oriental) até acertar a sua. Isto se ele conhecesse o assunto, o que
não ocorre com a maioria das pessoas.

No CityDesk, software de gerência de sítios web, publicado por minha empresa, decidimos que sua
codificação interna seria toda em Unicode UCS-2 (dois bytes), que é o que o Visual Basic, o COM e
o Windows NT/2000 usam na sua cadeia nativa de caracteres. No código C++ as cadeias são
declaradas como wchar_t ("wide char") ao invés de char e utilizam as funções wcs ao invés das str
(por exemplo wcscat e wcslen ao invés de strcat e strlen). Para criar uma cadeia literal em código
C basta pôr um L antes como em: L"Hello".
Ao publicar uma página web, o CityDesk a converte para a codificação UTF-8 que é bem suportada
por navegadores há muitos anos. Esta é a forma em que todas as línguas do Joel on Software são
codificadas e não temos registro de qualquer reclamação de pessoas com dificuldade de exibi-las.
Este artigo ficou comprido, tenho claro que não poderia esgotar o assunto de codificação de
caracteres e Unicode nele, mas espero que se o leitor chegou até aqui, aprendeu o suficiente para
retornar, usando agora antibiótico em vez de sanguessuga e magia, a programar, trabalho para o
qual os deixo e volto agora.
Sobre o autor: Sou seu anfitrião, Joel Spolsky, um desenvolvedor de software na cidade de Nova
Iorque. Desde 2000 escrevo sobre desenvolvimento de software, gerência, negócios e a Internet
neste sítio. Meu trabalho do dia-a-dia é a Fog Creek Software, que publica o FogBugz – o software,
de nome estúpido, para o acompanhamento esperto de bugs e o Fog Creek Copilot – que oferece a
forma mais tranqüila de proporcionar suporte remoto via Internet, sem nenhuma instalação ou
configuração. No Brasil, você pode navegar nos meus sites em português Fog Creek e Joel on
software, além disso tenho uma parceria com a Olympya TI que suporta os clientes brasileiros.

Sobre o Tradutor:
Paulo André de Andrade é Engenheiro Eletrônico e Diretor da OLYMPYA TI, responsável, no
Brasil, pela comercialização dos softwares da Fog Creek. Paulo André atua em Informática desde
1971 em setores que vão de Engenharia de Qualificação de Componentes para Hardware,
Engenharia de Produtos de Hardware, Desenvolvimento de Hardware e Software, Desenvolvimento
de Negócios, Marketing e Vendas de Software e Consultoria em Gerência de Projetos e em Serviços
de Informática.
OLYMPYA SOFTWARE
Baseada no Rio de Janeiro a OLYMPYA foi fundada em 2000 por Paulo Mattos e Paulo Mattos Sr.
com foco no desenvolvimento de plataformas de jogos MMO (Massively Multiplayer Online)
Sports Strategy Games e em Consultoria em Tecnologia da Informação.
A Olympya também é representante de um novo produto da FogCreek, para treinamento em
engenharia de software. Este novo produto foi lançado desde o inicio em Português veja mais
detalhes em:

http://training.fogcreek.com.br – venda sem instrutor.

Para ver a nossa oferta que inclui assistência com nossos instrutores na Avenida Paulista, em
Copacabana ou na sua empresa, veja:

http://www.scribd.com/doc/29112680/Make‐Better‐Software‐V1

Das könnte Ihnen auch gefallen