Caracteres Unicode: o que todo desenvolvedor deve saber





Se você está escrevendo um aplicativo internacional que usa vários idiomas, precisa saber algumas coisas sobre codificação. Ela é responsável pela forma como o texto é exibido na tela. Falarei brevemente sobre a história da codificação e sua padronização e, em seguida, falaremos sobre seu uso. Vamos tocar um pouco na teoria da informática.



Introdução à codificação



Os computadores entendem apenas números binários - zeros e uns, esta é a linguagem deles. Nada mais. Um número é denominado byte, cada byte é composto por oito bits. Ou seja, oito zeros e uns constituem um byte. Dentro dos computadores, tudo se resume a binários - linguagens de programação, movimentos do mouse, pressionamentos de teclas e todas as palavras na tela. Mas se o artigo que você está lendo costumava ser um monte de zeros e uns, como os números binários se tornaram texto? Vamos descobrir.



Uma breve história da codificação



No início de seu desenvolvimento, a Internet era exclusivamente anglófona. Seus autores e usuários não precisaram se preocupar com os caracteres de outras línguas, e todas as necessidades foram totalmente cobertas pela codificação American Standard Code for Information Interchange (ASCII).



ASCII é uma tabela para mapear símbolos binários em caracteres do alfabeto. Quando o computador recebe uma entrada como esta:



01001000 01100101 01101100 01101100 01101111 00100000 01110111 01101111 01110010 01101100 01100100

      
      





em seguida, usando ASCII, ele o converte na frase "Olá, mundo".



Um byte (oito bits) era grande o suficiente para conter qualquer letra do idioma inglês, bem como caracteres de controle, alguns dos quais eram usados ​​por teleimpressores, então naqueles anos eles eram úteis (hoje não são mais muito úteis). Os caracteres de controle eram, por exemplo, 7 (0111 em binário), que fazia com que o computador emitisse um sinal; 8 (1000 em binário) - exibe o último caractere impresso; ou 12 (1100 em binário) - apagou todo o texto escrito no terminal de vídeo.



Naquela época, os computadores contavam 8 bits por byte (nem sempre era o caso), então não havia problema. Poderíamos armazenar todos os caracteres de controle, todos os números e letras inglesas, e ainda havia espaço, já que um byte pode codificar 255 caracteres, e o ASCII só precisa de 127. Ou seja, ainda havia 128 posições na codificação não utilizadas.



Esta é a aparência de uma tabela ASCII. Os números binários codificam todas as letras maiúsculas e minúsculas de A a Z e os números de 0 a 9. As primeiras 32 posições são reservadas para caracteres de controle não imprimíveis.





Problemas ASCII



As posições 128 a 255 estavam vazias. O público se perguntou como preenchê-los. Mas todos eles tinham ideias diferentes . O American National Standards Institute (ANSI) formula padrões para diferentes setores. Eles aprovaram as posições ASCII de 0 a 127. Ninguém as contestou. O problema estava nas demais posições.



Isso é o que preencheu as posições 128-255 nos primeiros computadores IBM:





Alguns rabiscos, ícones de fundo, operadores matemáticos e símbolos acentuados como é. Mas os desenvolvedores de outras arquiteturas de computador não apoiaram a iniciativa. Todos queriam implementar sua própria codificação na segunda metade do ASCII.



Todas essas terminações diferentes foram chamadas de páginas de código .



O que são páginas de código ASCII?



Aqui está uma coleção de mais de 465 páginas de código diferentes! Havia páginas diferentes, mesmo dentro do mesmo idioma, por exemplo, para grego e chinês. Como essa bagunça poderia ser padronizada? Ou pelo menos fazer funcionar entre idiomas diferentes? Ou entre diferentes páginas de código para o mesmo idioma? Em outros idiomas além do inglês? Os chineses têm mais de 100.000 caracteres. O ASCII não pode nem mesmo acomodar todos eles, mesmo se eles decidirem dar todas as posições vazias para caracteres chineses.



Este problema foi até chamado de Mojibake (bnop, krakozyabry). Isso é o que dizem sobre o texto distorcido, obtido com o uso de uma codificação incorreta. Traduzido do japonês, mojibake significa "conversão de caracteres".





Um exemplo de bnopni (krakozyabrov).



Algum tipo de loucura ...



Exatamente! Não havia chance de converter os dados de maneira confiável. A Internet é apenas uma conexão monstruosa de computadores ao redor do mundo. Imagine que todos os países decidam usar seus próprios padrões. Por exemplo, os computadores gregos aceitam apenas grego, enquanto os computadores ingleses só enviam inglês. É como gritar em uma caverna vazia, ninguém pode ouvir você.



ASCII não era mais adequado para a vida. Para a Internet mundial, algo diferente teve que ser criado, ou haveria centenas de páginas de código para lidar. A menos que você não quer para ler esses parágrafos.



֎֏ 0590 ֐ ׀ׁׂ׃ׅׄ׆ׇ



É assim que o Unicode nasceu



Unicode significa Universal Coded Character Set (UCS) e tem a designação oficial ISO / IEC 10646. Mas geralmente todos usam o nome Unicode.



Esse padrão ajudou a resolver problemas causados ​​por codificação e páginas de código. Ele contém muitos pontos de código ( pontos de código) atribuídos a caracteres de idiomas e culturas em todo o mundo. Ou seja, Unicode é um conjunto de caracteres . Pode ser usado para associar alguma abstração à letra à qual queremos nos referir. E isso é feito para todos os símbolos, até mesmo para os hieróglifos egípcios .



Alguém fez um ótimo trabalho combinando todos os caracteres em todos os idiomas com códigos exclusivos. Isto é o que parece:



«Hello World»

U+0048 :   H
U+0065 :   E
U+006C :   L
U+006C :   L
U+006F :   O
U+0020 : 
U+0057 :   W
U+006F :   O
U+0072 :   R
U+006C :   L
U+0064 :   D
      
      





O prefixo U + indica que este é um padrão Unicode e o número é uma conversão binária. O padrão usa notação hexadecimal, que é uma representação simplificada de números binários. Aqui você pode inserir qualquer coisa no campo e ver como é convertido para Unicode. E aqui você pode admirar todos os 143.859 pontos de código.



Vou esclarecer apenas no caso: estamos falando de um grande dicionário de pontos de código atribuídos a todos os tipos de símbolos. Este é um conjunto muito grande de símbolos, nada mais.



Resta adicionar o último ingrediente.



Unicode Transform Protocol (UTF)



UTF é um protocolo para codificação de pontos de código em Unicode. Está explicitado no padrão e permite codificar qualquer ponto de código. No entanto, existem diferentes tipos de UTF. Eles diferem no número de bytes usados ​​para codificar um item. UTF-8 usa um byte por ponto, UTF-16 usa dois bytes e UTF-32 usa quatro bytes.



Mas se temos três codificações diferentes, como sabemos qual é usada em um arquivo específico? Para isso, é utilizada uma Marca de Ordem de Byte (BOM), também chamada de Assinatura de Codificação. BOM é um marcador de dois bytes no início do arquivo que informa qual codificação é usada aqui.



Na Internet, UTF-8 é o mais comumente usado , também é escrito como preferencial no padrão HTML5, por isso darei a maior atenção.





Este gráfico foi construído em 2012, o UTF-8 estava se tornando a codificação dominante. E ainda é.





O gráfico mostra a prevalência de UTF-8.



O que é UTF-8 e como funciona?



O UTF-8 codifica em um byte cada ponto de código Unicode de 0 a 127 (como em ASCII). Ou seja, se você escreveu seu programa usando ASCII e seus usuários usam UTF-8, eles não notarão nada fora do comum. Tudo funcionará conforme o planejado. Observe como isso é importante. Precisávamos manter compatibilidade com versões anteriores do ASCII durante a adoção em massa do UTF-8. E essa codificação não quebra nada.



Como o nome sugere, um ponto de código consiste em 8 bits (um byte). Existem caracteres em Unicode que ocupam vários bytes (até 6). Isso é chamado de comprimento variável. Em diferentes idiomas, o número específico de bytes é diferente. Em inglês - 1, idiomas europeus (com alfabeto latino), hebraico e áraberepresentado por dois bytes por ponto de código. Para chinês, japonês, coreano e outros idiomas asiáticos , são usados ​​três bytes.



Se você precisa que um caractere ocupe mais de um byte, um padrão de bits é usado para indicar a transição - significa que o caractere continua nos próximos bytes.



E agora nós, como que por mágica, chegamos a um acordo sobre como codificar o cuneiforme sumério (Habr não o exibe), bem como os ícones de emoji !



Para resumir, primeiro lemos o BOM para determinar a versão de codificação, depois convertemos o arquivo em pontos de código Unicode e exibimos os caracteres do conjunto Unicode.



Finalmente sobre UTF



Códigos são chaves . Se eu postar a codificação errada, você não conseguirá ler nada. Lembre-se disso ao enviar e receber dados. Em nossas ferramentas do dia a dia, isso geralmente é abstraído, mas para nós, programadores, é importante entender o que está acontecendo nos bastidores.



Como definimos a codificação? Como o HTML é escrito em inglês e quase todas as codificações funcionam bem com o inglês, podemos especificar a codificação no início da seção <had>



.



<html lang="en">
<head>
  <meta charset="utf-8">
</head>

      
      





É importante fazer isso logo no início <had>



, pois a análise de HTML pode recomeçar se a codificação errada estiver sendo usada. Você também pode descobrir a versão de codificação no cabeçalho Content-Type da solicitação / resposta HTTP.



Se o documento HTML não contém nenhuma menção de codificação, a especificação HTML5 oferece uma solução interessante como a detecção de BOM . Com sua ajuda, podemos determinar a codificação usada pelo marcador de ordem de bytes (BOM).



É tudo?



O Unicode ainda não está completo. Como acontece com qualquer padrão, acrescentamos algo, removemos algo, oferecemos algo novo. Nenhuma das especificações está “completa”. Normalmente, há 1-2 lançamentos por ano, você pode encontrar a descrição aqui .



Recentemente, li sobre um bug muito interessante relacionado à exibição incorreta de caracteres Unicode russos no Twitter .



Se você leu até o fim, então você é ótimo. Eu sugiro que você faça sua lição de casa. Veja como os sites podem falhar ao usar a codificação errada. Eu aproveitei issoextensão para Google Chrome, mudou a codificação e tentou abrir páginas diferentes. A informação era completamente ilegível. Experimente você mesmo, como se parece um toco. Isso ajudará você a entender a importância da codificação.





Conclusão



Enquanto escrevia este artigo, conheci Michael Everson . Desde 1993, ele propôs mais de 200 alterações no Unicode, adicionando milhares de caracteres ao padrão. Em 2003, ele foi considerado o membro mais produtivo. Ele sozinho influenciou muito a face do Unicode. Michael é um dos que fizeram a Internet como a conhecemos hoje. Muito impressionante.



Espero ter conseguido mostrar a você para que servem as codificações, quais problemas elas resolvem e o que acontece quando falham.



All Articles