📌 24 de Julho, 2015

Encoding: O Mínimo Absoluto

Informática · Programação

Ao lidar com formandos e até programadores menos experientes deparo-me sempre com um problema generalizado: Desconhecimento profundo de todos os temas relacionados com codificação / encoding e especialmente da importância de utilizar UTF-8. O encoding é também visto como um “bicho de 7 cabeças”.

Comecemos por definir o que é encoding:

Encoding é a relação estabelecida pelos computadores entre os caracteres (que aparecem no ecrã) e sistemas de baixo nível (impulsos eléctricos) que permitem armazenar e transmitir informação. É o mecanismo que permite que dois computadores comuniquem por exemplo a letra A entre si e esta tenha o mesmo significado e representação gráfica em ambos.

A História Por Contar

Quando a linguagem C foi inventada tudo era simples, existia a tabela ASCII que padronizava o armazenamento e transmissão de caracteres recorrendo a uma relação entre cada caractere e um número inteiro. Eram suportados 128 caracteres.

Como a maior parte da tecnologia de computação é de origem norte-americana isto servia as necessidades já que em Inglês não existem acentuação gráfica complexa como acentos graves, agudos e outras marcas como a cedilha.

No entanto, com a ubiquidade crescente dos sistemas de computação, começou a ser necessário escrever e transmitir linguagens baseadas noutros alfabetos (Latim e Asiáticos) que incluíam mais caracteres. Isto era de todo impossível já que os computadores só suportavam os 128 caracteres da tabela ASCII.

Foram criados diversos mecanismos, menos importantes, para tentar resolver este problema que tentavam utilizar várias combinações de caracteres simples da tabela ASCII para representar caracteres mais complexos. Rapidamente percebeu-se que esta solução era inviável e foram criados novos esquemas de caracteres (alguns na imagem).

O problema parecia resolvido, era possível finalmente escrever várias línguas no mesmo computador! A solução era tão apetecível que até foram criados esquemas específicos para cada sistema operativo… Ou até um para suportar o símbolo do Euro quando este foi introduzido.

Infelizmente esta solução ideal transformou-se rapidamente num dos maiores desafios da computação moderna porque:

  • Foram criadas dezenas de esquemas de caracteres, alguns pouco consistentes de difícil implementação no software;
  • Os sistemas operativos teriam de suportar todos mais comuns para que fosse possível transmitir documentos de texto entre utilizadores de diferentes países / línguas ou sistemas;
  • Na transmissão as aplicações teriam de entender todos estes esquemas e negociar em tempo real qual seria utilizado.

Isto levou-nos a uma situação bastante má: até há uns anos era possível ver sites ou emails que apresentavam “artefactos estranhos” no sítio de acentos ou cedilhas — isto devia-se à negociação incorrecta ou falta de suporte ao encoding do site por parte do browser.

Porque não utilizar um esquema de caracteres mais completo entre os existentes na altura?

Os mais completos, para representar os seus caracteres mais altos necessitam mais bits e os mais baixos teria de incluir padding à esquerda (normalmente com zeros) para manter a coerência — Em alfabetos mais simples, como o Inglês, estaríamos a desperdiçar espaço.

Por exemplo: B em ASCII é representado por 42 já em ISO 8859-8 seria por 0042.

Unicode & UTF-8

Um grupo de pessoas inteligentes juntou-se para estudar soluções para o problema e fundaram o Unicode Consortium. Desenvolveram o sistema de code points onde a cada letra de cada alfabeto existente no mundo seria atribuído um código “mágico” único em hexadecimal — uma tabela ASCII em esteróides.

Por exemplo a palavra BLOG em code points seria representada como U+0042 U+004C U+004F U+0047. (Um U foi adicionado para servir de indicação ao software que se tratava de texto codificado em unicode.

Este sistema respondia directamente aos desafios já que:

  • Podia incluir qualquer caractere de qualquer alfabeto e ainda sobraria bastante espaço para caracteres necessários no futuro;
  • A identificação do encoding evitava problemas de negociação;
  • Standard aberto e universal recomendável a ser implementado em qualquer sistema de computação.

Para além do seu sucesso continuava a existir o problema do desperdício de espaço então consorcio desenvolveu, entre outros, o UTF-8 (Unicode 8).

Num documento UTF-8 é valida a mistura de ASCII, ou seja, estes suportam a mistura de caracteres em ASCII juntamente com todos os outros de qualquer alfabeto suportados pelo UTF-8.

Assim BLOG seria directamente representado como ASCII evitando o desperdício de espaço. Caso pretendêssemos transmitir CAÇA a palavra passava a C A U+00C7 A e depois a C A U+C7 A e por fim seria então convertida, através da tabela ASCII, na notação de baixo nível mais apropriada.

Este novo esquema resolve todos os problemas anteriores e foi rapidamente suportado pelos sistemas operativos. Já o software demorou um pouco mais a adopta-lo e a tirar partido devido ao desconhecimento dos programadores.

O Importante

Ao contrário do que muitos programadores pensam, não existe “plain-text”. Um ficheiro no bloco de notas (.txt) não é interpretado em todos os sistema da mesma forma, porque o encoding varia.

Ao utilizar ASCII estamos a dar suporte a apenas aos caracteres do alfabeto Inglês e a impedir que as nossas aplicações suportar utilizadores em todo o mundo — muitas vezes ao tentar inserir um caractere não suportado numa aplicação esta pode bloquear ou resultar em problemas de segurança.

Os esquemas precedentes ao UTF-8 desperdiçam espaço e a não suportam qualquer qualquer alfabeto que os nossos utilizadores possam utilizar. O UTF-8 é assim a solução, tendo o maior suporte possível de caracteres e ocupando o menor espaço.

Existem diversos detalhes históricos e técnicos sobre a evolução do Unicode que não foram abordados neste artigo. Encoding é um tema complexo e mesmo tentando simplificar este artigo acabou por se tornar bastante longo.