minicurso encoding
Post on 05-Dec-2014
1.689 Views
Preview:
DESCRIPTION
TRANSCRIPT
Encoding em aplicaçõesAndré Willik Valenti
Dextra Sistemas
Roteiro▒ Parte 1
▒ O que é e por que existe
▒ Parte 2▒ Como funciona▒ Por que dá errado
▒ Parte 3▒ Como faz pra dar certo
Parte 1
O que é e por que existe
O que é encoding?▒ Mais especificamente:
▒ Character encoding
▒ Também conhecido como:▒ Codificação de caracteres▒ Charset
Quem é o encoding?▒ O encoding é o culpado por:
▒ Programação Programação Programa褯
▒ José Luís Assunção Júnior José LuÃs Assunção Júnior Jos題 u Assun 褯 J r�
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!
O que é isto?
O que era aquilo?▒ Pedras?▒ Ovos?▒ Feijões brancos?▒ Glóbulos brancos?
O que era aquilo?▒ Resposta:
▒ Depende de interpretação
▒ Seu cérebro recebeu estímulos visuais (dados) e interpretou alguma coisa (informação)
O que era aquilo?
Estímulos visuais (dados)
↓
Processamento
↓
Interpretação (informação)
O que era aquilo?▒ Os mesmos dados deram origem a informações diferentes
▒ Vamos voltar à imagem em si
O que era aquilo?▒ Aquela era uma imagem JPEG. Mas o que seria uma imagem JPEG?
Uma imagem mesmo?
Um monte de pixels?
Um monte de bytes?
Um grande número binário?
1111111111011000111111111110000000000000000100000100101001000110100100101000110000000000000000100000001000000010000000001011111
...
O que era aquilo?▒ A resposta correta é:
▒ Todas são diferentes formas de enxergar a mesma coisa
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
Informação=
dados + formade interpretá-los
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
Encoding▒ Voltando à pergunta: onde NÃO usa encoding?▒ Em lugar nenhum. Tudo usa encoding!
Encoding▒ PNG é um encoding▒ JPEG é um encoding▒ MPEG é um encoding▒ MP3 é um encoding▒ PDF é um encoding▒ ...
▒ Alguém já usou algum CODEC?
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?
Parte 2
Como (não) funciona
Por que dá errado
História▒ Década de 60
▒ Mais de 60 maneiras diferentes de representar caracteres
▒ Cada fabricante implementava do seu jeito
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...
ASCII▒ American Standard Code for Information Interchange
▒ 7 bits
▒ 128 diferentes caracteres
ASCII▒ 0 – 31: controle
▒ Nulo▒ Início da transmissão▒ Quebra de linha
▒ 32 – 127: imprimíveis▒ Letras▒ Números▒ Símbolos
ASCII▒ Exemplos:
ASCII Decimal Hexa Binário
5 53 0x35 0110101
A 65 0x41 1000001
} 125 0x7D 1111101
ASCII▒ Intervalo válido
▒ Em binário: 0000000 – 1111111▒ Em hexadecimal: 0x00 – 0x7F
ASCII▒ Agora é só todo mundo começar a usar ASCII e jamais teremos problemas com caracteres novamente
▒ Tudo resolvido!
ASCII▒ Sabe que não...
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
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!
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)
Extensões para ASCII▒ Codepages
▒ 852 — "Slavic (Latin2)" (Central and Eastern European languages)
▒ 855 — Cyrillic▒ 857 — Turkish▒ 858 — "Multilingual" with euro symbol▒ 860 — Portuguese
Extensões para ASCII▒ Codepages
▒ 863 — French (Quebec French) ▒ 865 — Danish/Norwegian▒ 866 — Cyrillic ▒ 869 — Greek ▒ 874 — Thai
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:
ASCII▒ No fim das contas, ficou assim:
▒ 0x00 – 0x7F: ASCII normal▒ 0x80 – 0xFF: ASCII estendido
ASCII▒ Na prática:
▒ 0x00 – 0x7F: blz! ▒ 0x80 – 0xFF: não blz
Encodings▒ Início dos diversos encodings
▒ e dos diversos problemas
Encodings▒ No Brasil, o codepage 850 era muito usado
Exemplo▒ Você, aqui no Brasil, gostaria de dar o seu olá
▒ Se você escrever:▒ Ola!
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.
Exemplo▒ Para um computador, não existe:
▒ Ola!
▒ O que existe são estes 4 bytes (ASCII):▒ 0x4F 0x6C 0x61 0x21
Exemplo▒ Blz !
▒ O l a !▒ ↑ ↑ ↑ ↑▒ 0x4F 0x6C 0x61 0x21
Exemplo▒ Qualquer computador que entenda ASCII (e todos entendem) vai conseguir processar corretamente a sua informação
Exemplo▒ E se a gente escrever...
▒ Olá!
Exemplo▒ Blz !▒ Pois:
▒ O l á !▒ ↑ ↑ ↑ ↑▒ 0x4F 0x6C 0xE1 0x21
Exemplo▒ Até você tentar ler isso num computador russo e...
Exemplo▒ Não blz ▒ Pois:
▒ O l р !▒ ↑ ↑ ↑ ↑▒ 0x4F 0x6C 0xE1 0x21
Exemplo▒ Quem foi que falou que 0xE1 corresponde ao caractere á???▒ Codepage 850 falou!
▒ Mas codepage 855 falou que 0xE1 equivale a р!
▒ Quem está certo???
Exemplo▒ Ou seja:
Exemplo▒ Não blz ▒ Pois:
▒ O l á !▒ ↑ ↑ ↑ ↑▒ 0x4F 0x6C ???? 0x21
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...
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
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
Encodings▒ Seria necessário...
▒ Um código...▒ Um código único...▒ Um único código...▒ Um...
UNICODE!!
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
The Unicode 5.0 Standard
▒ 1472 páginas▒ É grande
O que é Unicode?▒ Padrão internacional▒ Complexo▒ Extenso▒ Detalhado
O que é Unicode?▒ Duas partes interessantes para nós nesse momento:▒ UCS
▒Universal Character Set
▒ Encodings▒UTF8, UTF16, UTF32 (Unicode Transformation Format)
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
UCS▒ Exemplos:
▒ U+0058: X▒ U+00E3: ã▒ U+2603: ☃▒ U+10123:
UCS▒ Caracteres mais usados estão no intervalo U+0000 a U+FFFF
▒ Esse intervalo é chamado de Basic Multilingual Plane (BMP)
UCS▒ Caracteres na tabela são abstratos (são informação)
▒ Para concretizálos, é necessário um encoding
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
UTF32▒ Exemplos:
▒ U+0058: 0x00 0x00 0x00 0x58▒ U+00E3: 0x00 0x00 0x00 0xE3▒ U+2603: 0x00 0x00 0x26 0x03▒ U+10123: 0x00 0x01 0x01 0x23
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
UTF16▒ Exemplos:
▒ U+0058: 0x00 0x58▒ U+00E3: 0x00 0xE3▒ U+2603: 0x26 0x03▒ U+10123: 0xD8 0x00 0xDD 0x23
UTF8▒ Usa, no mínimo, 8 bits (1 byte) por caractere
▒ Pode usar de 1 a 4 bytes
▒ Parece o mais simples, mas na verdade é o mais complicado
UTF8▒ Exemplos:
▒ U+0058: 0x58▒ U+00E3: 0xC3 0xA3▒ U+2603: 0xE2 0x98 0x83▒ U+10123: 0xF0 0x90 0x84 0xA3
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
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”)
Adendo...▒ Mas isso é só um detalhe irrelevante nesse momento
UCS e UTF▒ O que eu preciso saber disso tudo?
▒ Apenas o seguinte:
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)
No mundo real de hoje▒ Encodings mais usados nos sistemas que rodam no Brasil:▒ UTF8▒ LATIN1
LATIN1▒ Também conhecido como ISO88591▒ Define 255 caracteres▒ Similar ao codepage 850▒ 1 byte por caractere (é fixo)
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
LATIN1▒ Relação com Unicode
▒ Caracteres LATIN1 (0x00 a 0xFF) são exatamente os mesmos que U+0000 até U+00FF
LATIN1▒ Exemplos
CaractereCode point (Unicode)
Código em LATIN1
X U+0058 0x58
ã U+00E3 0xE3
☃ U+2603 Não existe
U+10123 Não existe
LATIN1 e UTF8▒ Agora que já vimos LATIN1 e UTF8, voltemos à seguinte questão:
LATIN1 e UTF8▒ Por que “José” vira “José”???
LATIN1 e UTF8▒ “José” em UTF8:
▒ J o s é▒ ↑ ↑ ↑ ↑▒ 0x4A 0x6F 0x73 0xC3 0xA9
▒ Bytes 0x4A 0x6F 0x73 0xC3 0xA9 representam “José” em UTF8
LATIN1 e UTF8▒ Mas se você não avisar que está em UTF8 e alguém tentar ler em LATIN1:
▒ J o s à ©▒ ↑ ↑ ↑ ↑ ↑▒ 0x4A 0x6F 0x73 0xC3 0xA9
LATIN1 e UTF8▒ Toda vez que você envia uma sequência de bytes e não envia o encoding junto, corre o risco de ser malinterpretado
Parte 3
Como faz pra dar certo
Informação=
dados + formade interpretá-los
No caso de caracteres...
String..
=..bytes + encoding
Como faz pra dar certo▒ A primeira coisa a se ter na cabeça é:
Não existe string sem encoding!
Como faz pra dar certo▒ A segunda coisa a se ter na cabeça é:
Não existem bytes representando caracteres sem
encoding!
Como faz pra dar certo▒ Diretrizes para se evitar problemas de encoding:
Como faz pra dar certo▒ 1) Use sequências de escape sempre que possível
▒ Para escrever “Programação”:▒ Em Java:
▒"Programa\u00e7\u00e3o"▒ Em HTML:
▒<p>Programação</p>
Como faz pra dar certo▒ 2) Trate strings como strings
▒ Strings NÃO SÃO vetores de bytes!
Como faz pra dar certo▒ 3) Trate vetores de bytes como vetores de bytes
▒ Vetores de bytes NÃO SÃO strings!
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
Como faz pra dar certo▒ Exemplos:
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
Como faz pra dar certo
public int buscarAAcentuado(String str) {
return str.indexOf('\u00e1');
}
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
Como faz pra dar certo▒ Certo:
▒ ContentType: text/plain; charset=utf8
▒ ContentType: text/plain; charset=iso88591
▒ Errado:▒ ContentType: text/plain (não existe texto sem encoding!)
Como faz pra dar certo▒ Recomendado:
▒ UTF8▒<form acceptcharset="utf8">▒ContentType: application/xwwwformurlencoded; charset=utf8
▒ LATIN1▒<form acceptcharset="iso88591">▒ContentType: application/xwwwformurlencoded; charset= iso88591
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
Como faz pra dar certo▒ Vai baixar um JSON da internet?
▒ Caso fácil▒ Caso bizarro
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
Como faz pra dar certo▒ JSON – caso bizarro (codificado em LATIN1)▒ ???▒ Isso foge da especificação!
▒Fazer o quê... Acontece!▒ Processeo em LATIN1 mesmo...
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
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
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?”
Como faz pra dar certo▒ Funciona!
▒ ...às vezes!
▒ O que acontece se eu não especificar encoding?▒ Nenhum encoding será usado!▒ Certo!?
!!!!!!!!!!!
!!ERRADO!!
!!!!!!!!!!!
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!
Como faz pra dar certo▒ Plataformas MUDAM!▒ Configurações de ambiente MUDAM!▒ Encoding padrão MUDA!
Dica em Java▒ byte[] meusBytes =
string.getBytes("UTF8");
▒ String minhaString =new String(bytes, "UTF8");
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
Conclusões▒ Problemas de encoding acontecem nas melhores famílias
Conclusões▒ Qualquer peça do quebracabeça pode estragar tudo
▒ Programação defensiva costuma ser a melhor (e talvez a única) solução
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
Conclusões▒ Apenas reforçando:
▒ Não existe informação sem forma de interpretação
▒ Não existe string sem encoding
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
Referências▒ Lista de caracteres Unicode e suas diferentes representações▒ http://www.fileformat.info/info/unicode/
Referências▒ ASCII
▒ http://en.wikipedia.org/wiki/ASCII
▒ Unicode▒ http://en.wikipedia.org/wiki/Unicode
▒ UTF8▒ http://en.wikipedia.org/wiki/UTF8
top related