O que é Unicode, UTF-8, UTF-16?

395

Qual é a base do Unicode e por que a necessidade de UTF-8 ou UTF-16? Eu pesquisei isso no Google e procurei aqui também, mas não está claro para mim.

No VSS, ao fazer uma comparação de arquivos, às vezes há uma mensagem dizendo que os dois arquivos têm UTFs diferentes. Por que isso seria o caso?

Por favor, explique em termos simples.

SoftwareGeek
fonte
123
Parece que você precisa ler O mínimo absoluto que todo desenvolvedor de software deve saber absolutamente, positivamente sobre Unicode e conjuntos de caracteres ! É uma explicação muito boa do que está acontecendo.
111310 Brian Agnew
5
Este FAQ do site oficial Unicode tem algumas respostas para você.
Nemanja Trifunovic
4
@ John: é uma muito boa introdução, mas não é a melhor fonte: Ele ignora completamente alguns dos detalhes (o que é bom para uma visão geral / introdução!)
Joachim Sauer
5
O artigo é excelente, mas possui vários erros e representa o UTF-8 de uma maneira um tanto conservadora. Sugiro a leitura de utf8everywhere.org como um complemento.
Pavel Radzivilovsky
2
Dê uma olhada neste site: utf8everywhere.org
Vertexwahn

Respostas:

550

Por que precisamos de Unicode?

Nos (não muito) primeiros dias, tudo o que existia era ASCII. Tudo bem, pois tudo o que seria necessário eram alguns caracteres de controle, pontuação, números e letras como os desta frase. Infelizmente, o estranho mundo da intercomunicação global e das mídias sociais de hoje não estava previsto, e não é incomum ver Inglês, العربية, 汉语, עִבְרִית, ελληνικά e ភាសាខ្មែរ no mesmo documento (espero não ter quebrado nenhum velho navegadores).

Mas, por uma questão de argumento, digamos que Joe Average é desenvolvedor de software. Ele insiste que só precisará usar o inglês e, como tal, só quer usar o ASCII. Isso pode ser bom para Joe, o usuário , mas não é bom para Joe, o desenvolvedor de software . Aproximadamente metade do mundo usa caracteres não latinos e o uso de ASCII é indiscutível para essas pessoas; além disso, ele está fechando seu software para uma economia grande e crescente.

Portanto, é necessário um conjunto de caracteres abrangente, incluindo todos os idiomas. Assim veio o Unicode. Ele atribui a cada caractere um número exclusivo chamado ponto de código . Uma vantagem do Unicode sobre outros conjuntos possíveis é que os primeiros 256 pontos de código são idênticos ao ISO-8859-1 e, portanto, também ao ASCII. Além disso, a grande maioria dos caracteres comumente usados ​​é representável por apenas dois bytes, em uma região chamada BMP (Basic Multilingual Plane) . Agora é necessária uma codificação de caracteres para acessar esse conjunto de caracteres e, conforme a pergunta, vou me concentrar em UTF-8 e UTF-16.

Considerações sobre memória

Então, quantos bytes dão acesso a quais caracteres nessas codificações?

  • UTF-8:
    • 1 byte: ASCII padrão
    • 2 bytes: árabe, hebraico, a maioria dos scripts europeus (principalmente os georgianos )
    • 3 bytes: BMP
    • 4 bytes: todos os caracteres Unicode
  • UTF-16:
    • 2 bytes: BMP
    • 4 bytes: todos os caracteres Unicode

Vale ressaltar agora que os personagens que não estão no BMP incluem scripts antigos, símbolos matemáticos, símbolos musicais e caracteres chineses / japoneses / coreanos (CJK) mais raros .

Se você estiver trabalhando principalmente com caracteres ASCII, o UTF-8 certamente será mais eficiente em termos de memória. No entanto, se você estiver trabalhando principalmente com scripts não europeus, o uso de UTF-8 pode ter até 1,5 vezes menos eficiência de memória que o UTF-16. Ao lidar com grandes quantidades de texto, como páginas da Web grandes ou documentos extensos do Word, isso pode afetar o desempenho.

Noções básicas de codificação

Nota: Se você souber como UTF-8 e UTF-16 são codificados, pule para a próxima seção para aplicações práticas.

  • UTF-8: Para os caracteres ASCII padrão (0-127), os códigos UTF-8 são idênticos. Isso torna o UTF-8 ideal se a compatibilidade com versões anteriores for necessária com o texto ASCII existente. Outros caracteres requerem de 2 a 4 bytes. Isso é feito reservando alguns bits em cada um desses bytes para indicar que faz parte de um caractere de vários bytes. Em particular, o primeiro bit de cada byte é 1evitar colidir com os caracteres ASCII.
  • UTF-16: Para caracteres BMP válidos, a representação UTF-16 é simplesmente seu ponto de código. No entanto, para caracteres não BMP, o UTF-16 introduz pares substitutos . Nesse caso, uma combinação de duas partes de dois bytes é mapeada para um caractere não BMP. Essas partes de dois bytes vêm do intervalo numérico BMP, mas são garantidas pelo padrão Unicode como inválidas como caracteres BMP. Além disso, como o UTF-16 possui dois bytes como unidade básica, ele é afetado pela resistência . Para compensar, uma marca de ordem de bytes reservada pode ser colocada no início de um fluxo de dados que indica endianness. Portanto, se você estiver lendo a entrada UTF-16 e nenhuma endianness for especificada, deverá verificar isso.

Como pode ser visto, UTF-8 e UTF-16 não são nem de longe compatíveis entre si. Portanto, se você estiver executando E / S, saiba qual codificação está usando! Para mais detalhes sobre essas codificações, consulte as Perguntas frequentes sobre UTF .

Considerações práticas de programação

Tipos de dados de caracteres e seqüências de caracteres: como eles são codificados na linguagem de programação? Se forem bytes brutos, no minuto em que você tentar gerar caracteres não ASCII, poderá ter alguns problemas. Além disso, mesmo que o tipo de caractere seja baseado em uma UTF, isso não significa que as seqüências de caracteres sejam UTF adequadas. Eles podem permitir seqüências de bytes ilegais. Geralmente, você precisará usar uma biblioteca que suporte UTF, como ICU para C, C ++ e Java. De qualquer forma, se você deseja inserir / produzir algo diferente da codificação padrão, precisará convertê-lo primeiro.

Codificações recomendadas / padrão / dominantes: quando é possível escolher qual UTF usar, geralmente é melhor seguir os padrões recomendados para o ambiente em que você está trabalhando. Por exemplo, o UTF-8 é dominante na web e, desde o HTML5, ele foi a codificação recomendada . Por outro lado, os ambientes .NET e Java são baseados em um tipo de caractere UTF-16. De maneira confusa (e incorreta), frequentemente são feitas referências à "codificação Unicode", que geralmente se refere à codificação UTF dominante em um determinado ambiente.

Suporte de biblioteca: as bibliotecas que você está usando suportam algum tipo de codificação. Qual? Eles suportam os casos de canto? Como a necessidade é a mãe da invenção, as bibliotecas UTF-8 geralmente suportam caracteres de 4 bytes corretamente, pois caracteres de 1, 2 e até 3 bytes podem ocorrer com freqüência. No entanto, nem todas as supostas bibliotecas UTF-16 suportam pares substitutos corretamente, pois ocorrem muito raramente.

Contando caracteres: Existem caracteres combinados em Unicode. Por exemplo, o ponto de código U + 006E (n) e U + 0303 (um til de combinação) formam ñ, mas o ponto de código U + 00F1 forma ñ. Eles devem parecer idênticos, mas um algoritmo de contagem simples retornará 2 para o primeiro exemplo, 1 para o último. Isso não é necessariamente errado, mas também pode não ser o resultado desejado.

Comparando para igualdade: A, А e Α têm a mesma aparência, mas são latim, cirílico e grego, respectivamente. Você também tem casos como C e Ⅽ, um é uma letra e o outro, um número romano. Além disso, também temos os caracteres combinados a serem considerados. Para mais informações, consulte Caracteres duplicados em Unicode .

Pares substitutos: eles surgem com frequência suficiente no SO, então fornecerei alguns exemplos de links:

Outras?:

DPenner1
fonte
11
Resposta excelente, grandes chances para a recompensa ;-) Pessoalmente, eu acrescentaria que alguns defendem UTF-8 como a codificação universal de caracteres , mas sei que essa é uma opinião que não é necessariamente compartilhada por todos.
Joachim Sauer
3
Ainda muito técnico para mim nesta fase. Como a palavra hello é armazenada em um computador em UTF-8 e UTF-16?
Nome Sobrenome
11
Você poderia expandir mais sobre por que, por exemplo, o BMP ocupa 3 bytes em UTF-8? Eu teria pensado que, como seu valor máximo é 0xFFFF (16 bits), levaria apenas 2 bytes para acessar.
marca de
2
@mark Alguns bits são reservados para fins de codificação. Para um ponto de código que ocupa 2 bytes em UTF-8, existem 5 bits reservados, deixando apenas 11 bits para selecionar um ponto de código. U + 07FF acaba sendo o ponto de código mais alto representável em 2 bytes.
precisa saber é o seguinte
11
BTW - ASCII define apenas 128 pontos de código, usando apenas 7 bits para representação. É ISO-8859-1 / ISO-8859-15 que define 256 pontos de código e usa 8 bits para representação. Os primeiros 128 pontos de código em todos esses três são iguais.
Tuxdude 15/02
67
  • Unicode
    • é um conjunto de caracteres usados ​​em todo o mundo
  • UTF-8
    • uma codificação de caracteres capaz de codificar todos os caracteres possíveis (chamados pontos de código) no Unicode.
    • unidade de código é de 8 bits
    • use uma a quatro unidades de código para codificar Unicode
    • 00100100 para " $ " (um de 8 bits); 11000010 10100010 para " ¢ " (dois de 8 bits); 11100010 10000010 10101100 para " " (três 8 bits)
  • UTF-16
    • outra codificação de caracteres
    • a unidade de código é de 16 bits
    • use uma a duas unidades de código para codificar Unicode
    • 00000000 00100100 para " $ " (um de 16 bits); 11011000 01010010 11011111 01100010 para " 𤭢 " (dois 16 bits)
wengeezhang
fonte
11
Curto e preciso
Aritra Chatterjee
30

Unicode é um padrão bastante complexo. Não tenha muito medo, mas esteja preparado para algum trabalho! [2]

Como sempre é necessário um recurso confiável, mas o relatório oficial é enorme, sugiro que você leia o seguinte:

  1. O mínimo absoluto que todo desenvolvedor de software deve saber absolutamente, positivamente sobre conjuntos de caracteres e Unicode (sem desculpas!) Uma introdução por Joel Spolsky, CEO da Stack Exchange.
  2. Para o BMP e além! Um tutorial de Eric Muller, diretor técnico e vice-presidente mais tarde, no The Unicode Consortium. (primeiros 20 slides e pronto)

Uma breve explicação:

Os computadores leem bytes e as pessoas leem caracteres; portanto, usamos padrões de codificação para mapear caracteres para bytes. O ASCII foi o primeiro padrão amplamente utilizado, mas cobre apenas o latim (7 bits / caractere pode representar 128 caracteres diferentes). Unicode é um padrão com o objetivo de cobrir todos os caracteres possíveis no mundo (pode conter até 1.114.112 caracteres, o que significa 21 bits / caractere no máximo. O atual Unicode 8.0 especifica 120.737 caracteres no total, e isso é tudo).

A principal diferença é que um caractere ASCII pode caber em um byte (8 bits), mas a maioria dos caracteres Unicode não. Portanto, formulários / esquemas de codificação (como UTF-8 e UTF-16) são usados, e o modelo de caractere é assim:

Cada caractere mantém uma posição enumerada de 0 a 1.114.111 (hex: 0-10FFFF) chamada ponto de código .
Um formulário de codificação mapeia um ponto de código para uma sequência de unidades de código. Uma unidade de código é a maneira que você deseja que os caracteres sejam organizados na memória, unidades de 8 bits, unidades de 16 bits e assim por diante. O UTF-8 usa 1 a 4 unidades de 8 bits e o UTF-16 usa 1 ou 2 unidades de 16 bits, para cobrir todo o Unicode de no máximo 21 bits. As unidades usam prefixos para que os limites dos caracteres possam ser identificados, e mais unidades significam mais prefixos que ocupam bits. Portanto, embora o UTF-8 use 1 byte para o script latino, ele precisa de 3 bytes para scripts posteriores no Basic Multilingual Plane, enquanto o UTF-16 usa 2 bytes para todos esses. E essa é a principal diferença deles.
Por fim, um esquema de codificação (como UTF-16BE ou UTF-16LE) mapeia (serializa) uma sequência de unidades de código para uma sequência de bytes.

caractere: π
ponto do código: U + 03C0
formulários de codificação (unidades de código):
      UTF-8: CF 80
      UTF-16: 03C0
esquemas de codificação (bytes):
      UTF-8: CF 80
      UTF-16BE: 03 C0
      UTF-16LE: C0 03

Dica: um dígito hexadecimal representa 4 bits; portanto, um número hexadecimal de dois dígitos representa um byte.
Dê uma olhada nos mapas de avião na Wikipedia para ter uma ideia do layout do conjunto de caracteres

Neuron
fonte
19

Originalmente, o Unicode deveria ter uma codificação de 16 bits de largura fixa (UCS-2). Os primeiros usuários do Unicode, como Java e Windows NT, construíram suas bibliotecas em torno de cadeias de caracteres de 16 bits.

Posteriormente, o escopo do Unicode foi expandido para incluir caracteres históricos, o que exigiria mais do que os 65.536 pontos de código suportados por uma codificação de 16 bits. Para permitir que os caracteres adicionais sejam representados nas plataformas que usavam o UCS-2, a codificação UTF-16 foi introduzida. Ele usa "pares substitutos" para representar caracteres nos planos suplementares.

Enquanto isso, muitos softwares e protocolos de rede mais antigos estavam usando cadeias de caracteres de 8 bits. O UTF-8 foi criado para que esses sistemas pudessem suportar Unicode sem precisar usar caracteres largos. É compatível com versões anteriores com ASCII de 7 bits.

dan04
fonte
3
Vale a pena notar que a Microsoft ainda se refere ao UTF-16 como Unicode, aumentando a confusão. Os dois não são os mesmos.
Mark Ransom
15

Este artigo explica todos os detalhes http://kunststube.net/encoding/

ESCREVER PARA AMORTECEDOR

se você gravar em um buffer de 4 bytes, símbolo com codificação UTF8, seu binário ficará assim:

00000000 11100011 10000001 10000010

se você gravar em um buffer de 4 bytes, símbolo com codificação UTF16, seu binário ficará assim:

00000000 00000000 00110000 01000010

Como você pode ver, dependendo do idioma que você usaria no seu conteúdo, isso afetará sua memória de acordo.

Por exemplo, para este símbolo em particular: a codificação UTF16 é mais eficiente, pois temos 2 bytes sobressalentes para usar no próximo símbolo. Mas isso não significa que você deve usar o UTF16 para o alfabeto japonês.

LEITURA DO BUFFER

Agora, se você quiser ler os bytes acima, precisará saber em qual codificação foi gravada e decodificá-la novamente.

eg Se você decodificar este: 00000000 11100011 10000001 10000010 em codificação UTF16, você vai acabar com não

Nota: Codificação e Unicode são duas coisas diferentes. Unicode é o grande (tabela) com cada símbolo mapeado para um ponto de código exclusivo. por exemplo, o símbolo (letra) possui um (ponto de código) : 30 42 (hex). A codificação, por outro lado, é um algoritmo que converte símbolos de maneira mais apropriada ao armazenar em hardware.

30 42 (hex) - > UTF8 encoding - > E3 81 82 (hex), which is above result in binary.

30 42 (hex) - > UTF16 encoding - > 30 42 (hex), which is above result in binary.

insira a descrição da imagem aqui

InGeek
fonte
11

Unicode é um padrão que mapeia os caracteres em todos os idiomas para um valor numérico específico chamado Code Points . O motivo disso é que permite a possibilidade de codificações diferentes usando o mesmo conjunto de pontos de código.

UTF-8 e UTF-16 são duas dessas codificações. Eles recebem pontos de código como entrada e os codificam usando alguma fórmula bem definida para produzir a sequência codificada.

A escolha de uma codificação específica depende dos seus requisitos. Codificações diferentes têm requisitos de memória diferentes e, dependendo dos caracteres com os quais você estará lidando, você deve escolher a codificação que usa menos sequências de bytes para codificar esses caracteres.

Para obter detalhes mais detalhados sobre Unicode, UTF-8 e UTF-16, confira este artigo,

O que todo programador deve saber sobre Unicode

Kishu Agarwal
fonte
9

Por que unicode? Porque o ASCII possui apenas 127 caracteres. Os de 128 a 255 diferem em diferentes países, é por isso que existem páginas de código. Então eles disseram que vamos ter até 1114111 caracteres. Então, como você armazena o ponto de código mais alto? Você precisará armazená-lo usando 21 bits, para usar um DWORD com 32 bits e 11 bits desperdiçados. Portanto, se você usar um DWORD para armazenar um caractere unicode, é a maneira mais fácil, pois o valor em seu DWORD corresponde exatamente ao ponto de código. Mas as matrizes DWORD são obviamente maiores que as matrizes WORD e, é claro, ainda maiores que as matrizes BYTE. É por isso que não há apenas utf-32, mas também utf-16. Mas utf-16 significa um fluxo WORD, e um WORD possui 16 bits. Como o ponto de código mais alto 1114111 pode se encaixar em um WORD? Eu não posso! Então, eles colocam tudo mais que 65535 em um DWORD que eles chamam de par substituto. Esses pares substitutos são duas PALAVRAS e podem ser detectados observando os primeiros 6 bits. Então, e o utf-8? É uma matriz de bytes ou um fluxo de bytes, mas como o ponto de código mais alto 1114111 se encaixa em um byte? Eu não posso! Ok, então eles colocaram também um DWORD, certo? Ou possivelmente uma PALAVRA, certo? Quase certo! Eles inventaram sequências utf-8, o que significa que todo código de código maior que 127 deve ser codificado em uma sequência de 2 bytes, 3 bytes ou 4 bytes. Uau! Mas como podemos detectar essas seqüências? Bem, tudo até 127 é ASCII e é um byte único. O que começa com 110 é uma sequência de dois bytes, o que começa com 1110 é uma sequência de três bytes e o que começa com 11110 é uma sequência de quatro bytes. Os bits restantes desses chamados "startbytes" pertencem ao ponto de código. Agora, dependendo da sequência, os seguintes bytes devem ser seguidos. Um byte a seguir começa com 10, os bits restantes são 6 bits de carga útil e pertencem ao ponto de código. Concatene os bits da carga útil do startbyte e o seguinte byte / s, e você terá o ponto de código. Essa é toda a magia do utf-8.

brilhante
fonte
3
exemplo utf-8 do sinal € (Euro) decodificado na sequência utf-8 de 3 bytes: E2 = 11100010 82 = 10000010 AC = 10101100 Como você pode ver, o E2 começa com 1110, portanto esta é uma sequência de três bytes. , 82 e AC começam com 10, portanto estes são os seguintes bytes Agora concatenamos os "bits de carga": 0010 + 000010 + 101100 = 10000010101100, que é decimal 8364 Portanto, 8364 deve ser o ponto de código para o sinal € (Euro).
Brighty
5

ASCII - O software aloca apenas 8 bits de memória na memória para um determinado caractere. Funciona bem para caracteres em inglês e adotados (palavras de empréstimo como fachada), pois seus valores decimais correspondentes ficam abaixo de 128 no valor decimal. Exemplo de programa C.

UTF-8 - O software aloca 1 a 4 bytes variáveis ​​de 8 bits para um determinado caractere. O que significa variável aqui? Digamos que você esteja enviando o caractere 'A' através de suas páginas HTML no navegador (o HTML é UTF-8), o valor decimal correspondente de A é 65, quando você o converte em decimal, se torna 01000010. Isso requer apenas 1 bytes , 1 byte de memória é alocado mesmo para caracteres especiais em inglês adotados como 'ç' em uma fachada de palavras. No entanto, quando você deseja armazenar caracteres europeus, são necessários 2 bytes, portanto, você precisa de UTF-8. No entanto, quando você procura caracteres asiáticos, precisa de no mínimo 2 bytes e no máximo 4 bytes. Da mesma forma, os Emoji exigem de 3 a 4 bytes. UTF-8 resolverá todas as suas necessidades.

O UTF-16 alocará no mínimo 2 bytes e no máximo 4 bytes por caractere, não alocará 1 ou 3 bytes. Cada caractere é representado em 16 ou 32 bits.

Então, por que existe UTF-16? Originalmente, o Unicode era de 16 bits e não de 8 bits. Java adotou a versão original do UTF-16.

Em poucas palavras, você não precisa de UTF-16 em nenhum lugar, a menos que já tenha sido adotado pelo idioma ou plataforma em que está trabalhando.

O programa Java chamado pelos navegadores da Web usa UTF-16, mas o navegador da Web envia caracteres usando UTF-8.

Siva
fonte
"Você não precisa de UTF-16 em nenhum lugar, a menos que já tenha sido adotado pela linguagem ou plataforma": este é um bom ponto, mas aqui está uma lista não inclusiva: JavaScript, Java, .NET, SQL NCHAR, SQL NVARCHAR , VB4, VB5, VB6, VBA, VBScript, NTFS, API do Windows….
precisa
2

UTF significa sigla para Unicode Transformation Format. Basicamente, no mundo de hoje, existem scripts escritos em centenas de outros idiomas, formatos não cobertos pelo ASCII básico usado anteriormente. Portanto, a UTF passou a existir.

O UTF-8 possui recursos de codificação de caracteres e sua unidade de código é de 8 bits, enquanto que para o UTF-16 é de 16 bits.

Krishna Ganeriwal
fonte