O documento discute encodings e como eles afetam a representação de caracteres em computadores. Inicialmente, vários encodings foram usados, causando problemas de interoperabilidade. Posteriormente, o Unicode foi criado como um padrão único para mapear todos os caracteres, enquanto os encodings UTF-8, UTF-16 e UTF-32 permitem representá-los em bytes. Hoje, UTF-8 é o mais comum.
7. Encoding
▒ Por que se usa encoding?
▒ Onde NÃO se usa encoding?
▒ Segure essa ideia!
▒ Computador é uma máquina de
armazenar e processar informação
▒ Mas o que É informação?
▒ Segure essa ideia!
18. Um grande número binário?
11111111110110001111111111100000
00000000000100000100101001000110
10010010100011000000000000000010
0000001000000010000000001011111
...
19. O que era aquilo?
▒ A resposta correta é:
▒ Todas são diferentes formas de
enxergar a mesma coisa
20. O que era aquilo?
▒ A imagem é uma informação
▒ Pixels, bytes e bits são dados
▒ Dados são concretos. Informação é
abstrata.
▒ Informação = dados + forma de
interpretálos
22. Resumindo
▒ Informação
▒ O conceito abstrato a ser representado
▒ Exemplo: imagem
▒ Dados
▒ Representação concreta de informação
▒ Exemplo: sequência de bytes
▒ Encoding
▒ Forma de codificar informação em dados
▒ Exemplo: JPEG
23. Encoding
▒ Voltando à pergunta: onde NÃO
usa encoding?
▒ Em lugar nenhum. Tudo usa encoding!
24. Encoding
▒ PNG é um encoding
▒ JPEG é um encoding
▒ MPEG é um encoding
▒ MP3 é um encoding
▒ PDF é um encoding
▒ ...
▒ Alguém já usou algum CODEC?
25. Character encoding
▒ Um character encoding é uma
determinada maneira de se
representar caracteres
▒ Para refletir:
▒ Como se representam caracteres?
▒ É fácil representar caracteres?
▒ TXT é um encoding?
27. História
▒ Década de 60
▒ Mais de 60 maneiras diferentes de
representar caracteres
▒ Cada fabricante implementava do seu
jeito
28. História
▒ Bob Bemer:
▒ “Vamos uniformizar esse negócio...”
▒ Formouse um comitê do ANSI
(American National Standards
Institute) para essa tarefa
▒ 2 anos de trabalho depois...
36. ASCII
▒ Em vez de usar apenas 7 bits,
muitas máquinas usavam/usam 8
▒ E esse bit a mais aí?
▒ Mantém sempre 0
ou
▒ Usa como verificador de paridade
37. ASCII
▒ Ou melhor ainda!! Vamos fazer o
seguinte:
▒ Sabe esse oitavo bit aí que tá
sobrando?
▒ Vamos usar pra codificar caracteres
locais de cada país!
38. Extensões para ASCII
▒ Codepages
▒ 437 — The original IBM PC code page
▒ 720 — Arabic
▒ 737 — Greek
▒ 775 — Estonian, Lithuanian and
Latvian
▒ 850 — "Multilingual (Latin1)"
(Western European languages)
39. Extensões para ASCII
▒ Codepages
▒ 852 — "Slavic (Latin2)" (Central and
Eastern European languages)
▒ 855 — Cyrillic
▒ 857 — Turkish
▒ 858 — "Multilingual" with euro symbol
▒ 860 — Portuguese
41. ASCII
▒ Maravilha! Com dezenas de encodings
diferentes, todos poderão representar
seus caracteres!
▒ Mas e a interoperabilidade?
▒ Oras, quem é que vai precisar ler ou
escrever usando caracteres dos outros
países??
▒ O resultado todos já conhecem:
42.
43.
44.
45. ASCII
▒ No fim das contas, ficou assim:
▒ 0x00 – 0x7F: ASCII normal
▒ 0x80 – 0xFF: ASCII estendido
49. Exemplo
▒ Você, aqui no Brasil, gostaria
de dar o seu olá
▒ Se você escrever:
▒ Ola!
50. Exemplo
▒ Essa sua sequência de 4 caracteres é
uma informação
▒ Informação só existe na cabeça dos
seres humanos
▒ Computador não conhece informação.
Computador conhece dados.
51. Exemplo
▒ Para um computador, não existe:
▒ Ola!
▒ O que existe são estes 4 bytes
(ASCII):
▒ 0x4F 0x6C 0x61 0x21
57. Exemplo
▒ Não blz
▒ Pois:
▒ O l р !
▒ ↑ ↑ ↑ ↑
▒ 0x4F 0x6C 0xE1 0x21
58. Exemplo
▒ Quem foi que falou que 0xE1
corresponde ao caractere á???
▒ Codepage 850 falou!
▒ Mas codepage 855 falou que 0xE1
equivale a р!
▒ Quem está certo???
62. Exemplo
▒ Não blz
▒ Pois:
▒ O l á !
▒ ↑ ↑ ↑ ↑
▒ 0x4F 0x6C ???? 0x21
63. Encodings
▒ Não existe uma forma única de
representar o caractere á
▒ A sequência de bytes é ambígua:
▒ 0x4F 0x6C 0xE1 0x21
▒ A não ser que...
64. Encodings
▒ ...a gente envie para o
computador russo:
▒ A sequência de bytes
+
▒ o encoding usado (codepage 850)
▒ E reze para o computador russo
saber interpretar esse encoding
65. Encodings
▒ É óbvio que não iria dar certo o
mundo inteiro se comunicando
desse jeito, cada um com seu
encoding específico
▒ Seria necessário uniformizar de
verdade
68. Unicode
▒ O que é Unicode?
▒ A) Um código único
▒ B) Um encoding
▒ C) Uma tabela de caracteres
▒ D) Uma grande gambiarra
▒ E) Todas as anteriores
▒ F) Todas as anteriores e + um pouco
▒ G) Todas as anteriores + MUITA coisa
71. O que é Unicode?
▒ Padrão internacional
▒ Complexo
▒ Extenso
▒ Detalhado
72. O que é Unicode?
▒ Duas partes interessantes para nós
nesse momento:
▒ UCS
▒ Universal Character Set
▒ Encodings
▒ UTF8, UTF16, UTF32 (Unicode
Transformation Format)
73. UCS
▒ Tabela gigante de caracteres
▒ Cada caractere possui um código,
chamado code point
▒ Code point é representado por U+ e
um número em hexadecimal
75. UCS
▒ Caracteres mais usados estão no
intervalo U+0000 a U+FFFF
▒ Esse intervalo é chamado de
Basic Multilingual Plane (BMP)
76. UCS
▒ Caracteres na tabela são
abstratos (são informação)
▒ Para concretizálos, é
necessário um encoding
77. UTF32
▒ Usa exatamente 32 bits por caractere
(4 bytes)
▒ Simplesmente pega o code point e
preenche com zeros à esquerda, se
necessário
▒ Parece o mais complicado, mas na
verdade é o mais simples dos três
79. UTF16
▒ Usa, no mínimo, 16 bits por caractere (2
bytes)
▒ Para caracteres válidos do BMP, usa
exatamente 2 bytes
▒ Para caracteres fora do BMP, usa um mecanismo
similar à ideia de escape, e consome 4 bytes
▒ Sendo BMP o intervalo mais comum, UTF16
costuma usar exatamente 2 bytes por caractere
83. UTF8
▒ Compatível com ASCII entre
U+0000 e U+007F
▒ A partir de U+0080, usa mais de
um byte
▒ Para os caracteres da língua
portuguesa, usa 1 ou 2 bytes
84. Adendo...
▒ UTF16 e UTF32 possuem ainda
duas variações:
▒ BE – Big Endian
▒ LE – Little Endian
▒ Isso tem a ver com a ordem dos
bytes (no UTF16: “1º byte, 2º
byte” ou “2º byte, 1º byte”)
86. UCS e UTF
▒ O que eu preciso saber disso
tudo?
▒ Apenas o seguinte:
87. UCS e UTF
▒ Tabela de caracteres ≠ encoding
▒ Existem formas diferentes de se
representar caracteres Unicode. A
mais comum é usando UTF8.
▒ UTF8 usa número variável de bytes
por caractere (em geral, 1 ou 2)
88. No mundo real de hoje
▒ Encodings mais usados nos
sistemas que rodam no Brasil:
▒ UTF8
▒ LATIN1
89. LATIN1
▒ Também conhecido como ISO88591
▒ Define 255 caracteres
▒ Similar ao codepage 850
▒ 1 byte por caractere (é fixo)
90. LATIN1
▒ Mesma ideia dos ASCIIs
estendidos:
▒ 0x00 a 0x7F: igual ASCII
▒ 0x80 a 0xFF: outros caracteres
▒ NÃO é um encoding para Unicode
▒ 1 byte nem seria suficiente
91. LATIN1
▒ Relação com Unicode
▒ Caracteres LATIN1 (0x00 a 0xFF) são
exatamente os mesmos que U+0000 até
U+00FF
92. LATIN1
▒ Exemplos
Code point Código em
Caractere
(Unicode) LATIN1
X U+0058 0x58
ã U+00E3 0xE3
☃ U+2603 Não existe
U+10123 Não existe
93. LATIN1 e UTF8
▒ Agora que já vimos LATIN1 e
UTF8, voltemos à seguinte
questão:
106. Como faz pra dar certo
▒ Diretrizes para se evitar
problemas de encoding:
107. Como faz pra dar certo
▒ 1) Use sequências de escape
sempre que possível
▒ Para escrever “Programação”:
▒ Em Java:
▒ "Programau00e7u00e3o"
▒ Em HTML:
▒ <p>Programação</p>
108. Como faz pra dar certo
▒ 2) Trate strings como strings
▒ Strings NÃO SÃO vetores de bytes!
109. Como faz pra dar certo
▒ 3) Trate vetores de bytes como
vetores de bytes
▒ Vetores de bytes NÃO SÃO strings!
110. Como faz pra dar certo
▒ 4) Faça conversões só quando
realmente for necessário
▒ Ao fazer qualquer conversão, SEMPRE
especifique o encoding
▒ Quando é que realmente precisamos
fazer conversões?
▒ Quando fazemos entrada/saída
112. Como faz pra dar certo
▒ Você tem uma string na mão e quer
procurar ocorrências de uma letra
acentuada nela?
▒ Então nesse caso você NÃO PRECISA mexer com
encoding!
▒ Repare que não existe operação de
entrada/saída nesse caso
▒ Você deve apenas escapar o caractere
desejado, por segurança
113. Como faz pra dar certo
public int
buscarAAcentuado(String str) {
return str.indexOf('u00e1');
}
114. Como faz pra dar certo
▒ Você vai enviar texto em uma
requisição HTTP?
▒ Converta a string para bytes usando
algum encoding
▒ Avise ao servidor que você vai usar
esse encoding
▒ Envie os bytes
115. Como faz pra dar certo
▒ Certo:
▒ ContentType: text/plain; charset=utf8
▒ ContentType: text/plain; charset=iso8859
1
▒ Errado:
▒ ContentType: text/plain (não existe texto
sem encoding!)
116. Como faz pra dar certo
▒ Recomendado:
▒ UTF8
▒ <form acceptcharset="utf8">
▒ ContentType: application/xwwwform
urlencoded; charset=utf8
▒ LATIN1
▒ <form acceptcharset="iso88591">
▒ ContentType: application/xwwwform
urlencoded; charset= iso88591
117. Como faz pra dar certo
▒ Você vai fazer um proxy (baixar
conteúdo e enviálo para algum
outro lugar)?
▒ Baixe o conteúdo (bytes)
▒ Leia qual é o encoding do conteúdo
▒ Repasse o encoding
▒ Repasse os bytes
▒ Não mexa no conteúdo nem no encoding
118. Como faz pra dar certo
▒ Vai baixar um JSON da internet?
▒ Caso fácil
▒ Caso bizarro
119. Como faz pra dar certo
▒ JSON – caso fácil (codificado em
UTF8, UTF16 ou UTF32)
▒ Baixe o conteúdo (bytes)
▒ Repasse os bytes para a sua
biblioteca de processamento de JSON
▒ Padrão JSON define um mecanismo de
detecção automática de qual encoding
UTF foi usado
▒ Geralmente vai estar em UTF8
120. Como faz pra dar certo
▒ JSON – caso bizarro (codificado
em LATIN1)
▒ ???
▒ Isso foge da especificação!
▒ Fazer o quê... Acontece!
▒ Processeo em LATIN1 mesmo...
121. Como faz pra dar certo
▒ Vai baixar um XML da internet?
▒ Baixe o conteúdo (bytes)
▒ Repasse os bytes para a sua
biblioteca de processamento de XML
▒ XML informa seu encoding dentro do
próprio documento
122. Como faz pra dar certo
▒ Vai escrever um JSON seu para o cliente?
▒ Converta o JSON em string
▒ Converta a string em bytes usando UTF8
▒ Defina encoding de saída como sendo UTF8
▒ Escreva os bytes para o cliente
▒ Especificar charset de JSON não deveria ser
necessário, mas algumas implementações exigem.
Portanto, o melhor é fazer:
▒ ContentType: application/json;charset=utf8
123. Como faz pra dar certo
▒ “Você fica dizendo aí toda hora
que tem passar o encoding, tem
que passar encoding... E se eu
não passar o encoding? Não
funciona?”
124. Como faz pra dar certo
▒ Funciona!
▒ ...às vezes!
▒ O que acontece se eu não
especificar encoding?
▒ Nenhum encoding será usado!
▒ Certo!?
126. Como faz pra dar certo
▒ Se você não especificar encoding,
será usado o encoding padrão da
plataforma
▒ E isso é ERRADO!
▒ É um perigo!
▒ É um absurdo!
127. Como faz pra dar certo
▒ Plataformas MUDAM!
▒ Configurações de ambiente MUDAM!
▒ Encoding padrão MUDA!
128. Dica em Java
▒ byte[] meusBytes =
string.getBytes("UTF8");
▒ String minhaString =
new String(bytes, "UTF8");
129. Dica em Java
▒ Chamando sempre esses métodos e
passando o encoding correto, você
nunca gerará problemas de encoding no
seu código
▒ Apesar disso, nada impede de o
problema estar fora do seu código
▒ De qualquer forma, faça sua parte
131. Conclusões
▒ Qualquer peça do quebracabeça
pode estragar tudo
▒ Programação defensiva costuma
ser a melhor (e talvez a única)
solução
132. Conclusões
▒ Causas são sempre as mesmas:
▒ String sendo lida e/ou escrita
usando o encoding errado
▒ Uso indevido do encoding padrão da
plataforma
▒ Causa raiz de todo o problema:
▒ Ambiguidade: mais de uma maneira de
representar a mesma informação
134. Referências
▒ The Unicode Consortium
▒ http://unicode.org/
▒ The Absolute Minimum Every Software
Developer Absolutely, Positively Must
Know About Unicode and Character Sets
(No Excuses!)
▒ http://www.joelonsoftware.com/articles/Unicode.html
135. Referências
▒ Lista de caracteres Unicode e
suas diferentes representações
▒ http://www.fileformat.info/info/unicode/