it-swarm.dev

Qual é a diferença entre UTF-8 e Unicode?

Eu ouvi opiniões conflitantes de pessoas - de acordo com a página Wikipedia UTF-8 .

Eles são a mesma coisa, não são? Alguém pode esclarecer?

430
sarsnake

Para expandir as respostas que os outros deram:

Temos muitos idiomas com muitos caracteres que os computadores devem idealmente exibir. O Unicode atribui a cada caractere um número exclusivo ou um ponto de código.

Computadores lidam com números como bytes ... ignorando um pouco o histórico e ignorando problemas de endereçamento de memória, computadores de 8 bits tratariam um byte de 8 bits como a maior unidade numérica facilmente representada no hardware, computadores de 16 bits se expandiriam isso para dois bytes e assim por diante.

Codificações de caracteres antigos como ASCII são da era (pré-) de 8 bits e tentam encaixar a linguagem dominante na computação na época, isto é, o inglês, em números que variam de 0 a 127 (7 bits). ). Com 26 letras no alfabeto, tanto em forma de capital como não capital, números e sinais de pontuação, isso funcionou muito bem. ASCII foi estendido por um oitavo bit para outros idiomas que não o inglês, mas os 128 números/pontos de código adicionais disponibilizados por essa expansão seriam mapeados para diferentes caracteres, dependendo do idioma exibido. Os padrões ISO-8859 são as formas mais comuns desse mapeamento; ISO-8859-1 e ISO-8859-15 (também conhecidas como ISO-Latin-1, latin1 e yes existem duas versões diferentes do padrão 8859 ISO).

Mas isso não é suficiente quando você quer representar personagens de mais de um idioma, então não basta trabalhar com todos os caracteres disponíveis em um único byte.

Existem basicamente dois tipos diferentes de codificações: um expande o intervalo de valores adicionando mais bits. Exemplos dessas codificações seriam UCS2 (2 bytes = 16 bits) e UCS4 (4 bytes = 32 bits). Eles sofrem inerentemente o mesmo problema que os padrões ASCII e ISO-8859, já que sua faixa de valores ainda é limitada, mesmo se o limite for muito maior.

O outro tipo de codificação usa um número variável de bytes por caractere, e as codificações mais conhecidas para isso são as codificações UTF. Todas as codificações UTF funcionam aproximadamente da mesma maneira: você escolhe um tamanho de unidade, que para UTF-8 é de 8 bits, para UTF-16 é de 16 bits e para UTF-32 é de 32 bits. O padrão então define alguns desses bits como sinalizadores: se eles estiverem definidos, a próxima unidade em uma seqüência de unidades deve ser considerada parte do mesmo caractere. Se eles não estiverem definidos, esta unidade representa um caractere completo. Assim, os caracteres mais comuns (em inglês) ocupam apenas um byte em UTF-8 (dois em UTF-16, 4 em UTF-32), mas outros caracteres de idioma podem ocupar seis bytes ou mais.

Codificações multi-byte (devo dizer multi-unidade após a explicação acima) têm a vantagem de serem relativamente eficientes em termos de espaço, mas a desvantagem de que operações como encontrar substrings, comparações, etc., todas têm que decodificar os caracteres para codificar unicode pontos antes que tais operações possam ser realizadas (existem alguns atalhos, no entanto).

Os padrões UCS e os padrões UTF codificam os pontos de código, conforme definido em Unicode. Em teoria, essas codificações poderiam ser usadas para codificar qualquer número (dentro do intervalo que a codificação suporta) - mas é claro que essas codificações foram feitas para codificar pontos de código Unicode. E esse é o seu relacionamento entre eles.

O Windows lida com as strings "Unicode" como strings UTF-16, enquanto a maioria dos UNIXes é padronizada para UTF-8 atualmente. Protocolos de comunicação, como HTTP, tendem a funcionar melhor com UTF-8, já que o tamanho da unidade em UTF-8 é o mesmo que em ASCII, e a maioria desses protocolos foi projetada na era ASCII. Por outro lado, o UTF-16 oferece o melhor médio espaço/desempenho de processamento ao representar todas as linguagens vivas.

O padrão Unicode define menos pontos de código que podem ser representados em 32 bits. Assim, para todos os efeitos práticos, o UTF-32 e o UCS4 se tornaram a mesma codificação, já que é improvável que você tenha que lidar com caracteres de várias unidades em UTF-32.

Espero que preencha alguns detalhes.

434
unwesen

"Unicode" infelizmente é usado de várias maneiras diferentes, dependendo do contexto. Seu uso mais correto (IMO) é como um conjunto de caracteres codificados - ou seja, um conjunto de caracteres e um mapeamento entre os caracteres e inteiro pontos de código representando-os.

TF-8 é uma codificação de caracteres - uma maneira de converter seqüências de bytes em seqüências de caracteres e vice-versa. Abrange todo o conjunto de caracteres Unicode. ASCII é codificado como um único byte por caractere, e outros caracteres tomam mais bytes dependendo do seu ponto de código exato (até 4 bytes para todos os pontos de código atualmente definidos, ou seja, até U-0010FFFF e 4 bytes poderia lidar com até U-001FFFFF).

Quando "Unicode" é usado como o nome de uma codificação de caracteres (por exemplo, como a propriedade .NET Encoding.Unicode ) geralmente significa TF-16 , que codifica os caracteres mais comuns como dois bytes. Algumas plataformas (notavelmente .NET e Java) usam o UTF-16 como sua codificação de caracteres "nativa". Isso leva a problemas de pêlos se você precisa se preocupar com caracteres que não podem ser codificados em um único valor de UTF-16 (eles são codificados como "pares substitutos") - mas a maioria dos desenvolvedores nunca se preocupa com isso, IME.

Algumas referências no Unicode:

189
Jon Skeet

Deixe-me usar um exemplo para ilustrar este tópico:

A chinese character:      汉
it's unicode value:       U+6C49
convert 6C49 to binary:   01101100 01001001

Nada mágico até agora, é muito simples. Agora, digamos que decidimos armazenar esse personagem em nosso disco rígido. Para fazer isso, precisamos armazenar o caractere em formato binário. Podemos simplesmente armazená-lo como é '01101100 01001001'. Feito!

Mas espere um minuto, é '01101100 01001001' um caractere ou dois caracteres? Você sabia que este é um personagem porque eu te disse, mas quando um computador lê, não faz ideia. Então, precisamos de algum tipo de "codificação" para dizer ao computador para tratá-lo como um.

É aqui que entra a regra de 'UTF-8': http://www.fileformat.info/info/unicode/utf8.htm

Binary format of bytes in sequence

1st Byte    2nd Byte    3rd Byte    4th Byte    Number of Free Bits   Maximum Expressible Unicode Value
0xxxxxxx                                                7             007F hex (127)
110xxxxx    10xxxxxx                                (5+6)=11          07FF hex (2047)
1110xxxx    10xxxxxx    10xxxxxx                  (4+6+6)=16          FFFF hex (65535)
11110xxx    10xxxxxx    10xxxxxx    10xxxxxx    (3+6+6+6)=21          10FFFF hex (1,114,111)

De acordo com a tabela acima, se quisermos armazenar este personagem usando o formato 'UTF-8', precisamos prefixar nosso personagem com alguns 'cabeçalhos'. Nosso caractere chinês tem 16 bits (conte o valor binário), portanto, usaremos o formato na linha 3, pois ele fornece espaço suficiente:

Header  Place holder    Fill in our Binary   Result         
1110    xxxx            0110                 11100110
10      xxxxxx          110001               10110001
10      xxxxxx          001001               10001001

Escrevendo o resultado em uma linha:

11100110 10110001 10001001

Este é o valor UTF-8 (binário) do caractere chinês! (confirme você mesmo: http://www.fileformat.info/info/unicode/char/6c49/index.htm )

Resumo

A chinese character:      汉
it's unicode value:       U+6C49
convert 6C49 to binary:   01101100 01001001
embed 6C49 as UTF-8:      11100110 10110001 10001001
181
Cheng

Eles não são a mesma coisa - o UTF-8 é um modo particular de codificar Unicode.

Existem várias codificações diferentes que você pode escolher dependendo do aplicativo e dos dados que você pretende usar. Os mais comuns são UTF-8, UTF-16 e UTF-32, até onde eu sei.

107
Greg

O Unicode define apenas pontos de código, isto é, um número que representa um caractere. Como você armazena esses pontos de código na memória depende da codificação que você está usando. O UTF-8 é uma maneira de codificar caracteres Unicode, entre muitos outros.

60
Martin Cote

Unicode é um padrão que define, junto com ISO/IEC 10646, Conjunto Universal de Caracteres (UCS) que é um superconjunto de todos os caracteres existentes necessários para representar praticamente todos os idiomas conhecidos.

O Unicode atribui um Nome e um Número ( Código de Caractere , ou Código-Ponto ) para cada caractere em seu repertório.

A codificação UTF-8 , é uma maneira de representar esses caracteres digitalmente na memória do computador. O UTF-8 mapeia cada ponto de código em uma seqüência de octetos (bytes de 8 bits)

Por exemplo,

Caractere UCS = Caractere Han Unicode

Ponto de código UCS = U + 24B62

Codificação UTF-8 = F0 A4 AD A2 (hex) = 11110000 10100100 10101101 10100010 (bin)

28
nightlytrails

nicode é apenas um padrão que define um conjunto de caracteres ( UCS ) e codificações ( UTF ) para codificar este conjunto de caracteres. Mas, em geral, o Unicode é referenciado ao conjunto de caracteres e não ao padrão.

Read O Mínimo Absoluto Todo Desenvolvedor de Software Absolutamente, Positivamente Deve Saber Sobre Unicode e Conjuntos de Caracteres (Sem Desculpas!) e nicode Em 5 Minutos .

24
Gumbo

As respostas existentes já explicam muitos detalhes, mas aqui está uma resposta muito curta com a explicação mais direta e exemplo.

Unicode é o padrão que mapeia caracteres para pontos de código
Cada caractere possui um exclusivo codepoint (número de identificação), que é um número como 9731.

UTF-8 é um a  codificação dos pontos de código.
Para armazenar todos os caracteres no disco (em um arquivo), o UTF-8 divide os caracteres em até 4 octetos (seqüências de 8 bits) - bytes. O UTF-8 é uma das várias codificações (métodos de representação de dados). Por exemplo, em Unicode, o ponto de código (decimal) 9731 representa um boneco de neve (), que consiste em 3 bytes em UTF-8: E2 98 83

Aqui está um lista ordenada com alguns exemplos aleatórios .

21
basic6

1. Unicode

Existem muitos personagens ao redor do mundo, como "$, &, h, a, t,?, 张, 1, =, + ...".

Então chega uma organização que se dedica a esses personagens,

Eles fizeram um padrão chamado "Unicode".

O padrão é como segue:

  • crie um formulário no qual cada posição seja chamada de "ponto de código" ou "posição de código".
  • As posições inteiras são de U + 0000 a U + 10FFFF;
  • Até agora, algumas posições são preenchidas com caracteres e outras posições são salvas ou vazias.
  • Por exemplo, a posição "U + 0024" é preenchida com o caractere "$".

PS: Claro que há outra organização chamada ISO mantendo outro padrão - "ISO 10646", quase o mesmo.

2. UTF-8

Como acima, U + 0024 é apenas uma posição, então não podemos salvar "U + 0024" no computador para o caractere "$".

Deve haver um método de codificação.

Em seguida, chegam métodos de codificação, como UTF-8, UTF-16, UTF-32, UCS-2 ....

Sob UTF-8, o ponto de código "U + 0024" é codificado em 00100100.

00100100 é o valor que economizamos no computador para "$".

14
wengeezhang

Eu verifiquei os links na resposta do Gumbo, e queria colar algumas dessas coisas aqui no Stack Overflow também.

"... Algumas pessoas estão sob o equívoco de que Unicode é simplesmente um código de 16 bits, onde cada personagem recebe 16 bits e, portanto, existem 65.536 caracteres possíveis. Isso não é, na verdade, correto. É o único mito mais comum sobre Unicode Então, se você pensou assim, não se sinta mal.

Na verdade, o Unicode tem uma maneira diferente de pensar sobre os caracteres, e você precisa entender o modo Unicode de pensar nas coisas ou nada fará sentido.

Até agora, assumimos que uma carta mapeia para alguns bits que você pode armazenar no disco ou na memória:

A -> 0100 0001

Em Unicode, uma carta mapeia para algo chamado ponto de código, que ainda é apenas um conceito teórico. Como esse ponto de código é representado na memória ou no disco é uma história completamente diferente ... "

"... Cada letra platônica de cada alfabeto recebe um número mágico do consórcio Unicode que é escrito assim: U + 0639. Esse número mágico é chamado de ponto de código. O U + significa" Unicode "e os números são hexadecimais. U + 0639 é a letra árabe Ain. A letra inglesa A seria U + 0041 .... "

"... OK, então digamos que temos uma string:

Olá

que, em Unicode, corresponde a esses cinco pontos de código:

U + 0048 U + 0065 U + 006C U + 006C U + 006F.

Apenas um monte de pontos de código. Números, na verdade. Ainda não dissemos nada sobre como armazenar isso na memória ou representá-lo em uma mensagem de e-mail ... "

"... É onde entram as codificações.

A primeira ideia para a codificação Unicode, que levou ao mito sobre os dois bytes, foi, ei, vamos apenas armazenar esses números em dois bytes cada. Então Olá torna-se

00 48 00 65 00 6C 00 6C 00 6F

Certo? Não tão rápido! Não poderia ser também:

48 00 65 00 6C 00 6C 00 6F 00? ... "

12
kommradHomer

nicode é um padrão de amplo escopo que define mais de 130.000 caracteres e aloca um código numérico (um "ponto de código"). Ele também define regras sobre como classificar esse texto, normalizá-lo, alterar seu caso e muito mais. Um caractere em Unicode é representado por um ponto de código de zero até 0x10FFFF, inclusive, embora alguns pontos de código sejam reservados e não possam ser usados ​​para caracteres.

Os códigos em Unicode podem ser representados em mais de uma codificação. O mais simples é o UTF-32, que simplesmente codifica o ponto de código como inteiros de 32 bits, cada um com 4 bytes de largura.

TF-8 é outra codificação, e rapidamente se tornando o padrão de fato. Codifica como uma sequência de valores de bytes. Cada ponto de código pode usar um número variável desses bytes. Os pontos de código na faixa ASCII são codificados, para serem compatíveis com ASCII. Os pontos de código fora desse intervalo usam um número variável de bytes, 2, 3 ou 4, dependendo do intervalo em que estão.

UTF-8 foi projetado com estas propriedades em mente:

  • Os caracteres ASCII são codificados exatamente como estão em ASCII, de forma que uma cadeia ASCIItambém seja válida como UTF-8.

  • Ordenação binária: A classificação de sequências de caracteres UTF-8 usando uma classificação binária simples ainda resultará na classificação de todos os pontos de código em ordem numérica.

  • Caracteres fora do intervalo ASCIInão usam nenhum byte no intervaloASCII, assegurando que eles não possam ser confundidos com caracteres ASCII. Este também é um recurso de segurança.

  • O UTF-8 pode ser facilmente validado e distinguido de outras codificações de caracteres por um validador. O texto em outras codificações de 8 ou de vários bytes raramente será validado como UTF-8.

  • Acesso aleatório: Em qualquer ponto da string UTF-8, é possível dizer se o byte nessa posição é o primeiro byte de um caractere ou não, e voltar para o início desse caractere, sem precisar se referir a nada. o início da string.

3
thomasrutter

Eles são a mesma coisa, não são?

Não, eles não são


Acho que a primeira sentença do página da Wikipédia que você referenciou dá um breve resumo:

UTF-8 é uma codificação de caracteres de largura variável capaz de codificar todos os 1.112.064 pontos de código válidos em Unicode usando um a quatro bytes de 8 bits.

Para elaborar:

  • Unicode é um padrão, que define um mapa de caracteres para números, os chamados pontos de código , (como no exemplo abaixo). Para o mapeamento completo, você pode dar uma olhada aqui .

    ! -> U+0021 (21),  
    " -> U+0022 (22),  
    \# -> U+0023 (23)
    
  • O UTF-8 é uma das maneiras de codificar esses pontos de código em um formulário que um computador pode entender, também conhecido como bits . Em outras palavras, é uma maneira/algoritmo de converter cada um desses pontos de código em uma seqüência de bits ou converter uma seqüência de bits em pontos de código equivalentes. Note que existem muitas codificações alternativas para Unicode.


Joel dá uma explicação muito legal e uma visão geral da história aqui .

0
Dimos

TF-8 é um método para codificar caracteres Unicode usando sequências de 8 bits.

nicode é um padrão para representar uma grande variedade de caracteres de vários idiomas.

0
akaMahesh