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

Eu ouvi opiniões conflitantes de pessoas – de acordo com a Wikipedia, veja aqui .

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

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.

Os computadores lidam com números como bytes … ignorando um pouco o histórico e ignorando problemas de endereçamento de memory, 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.

As antigas codificações de caracteres, como ASCII, são da era (pré-) de 8 bits e tentam encheckboxr a linguagem dominante na computação na época, ou seja, o inglês, em números que variam de 0 a 127 (7 bits). Com 26 letras no alfabeto, tanto na forma de capital como fora do capital, números e sinais de pontuação, isso funcionou muito bem. O 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 conhecido como ISO-Latin-1, latin1 e yes existem duas versões diferentes do padrão 8859 ISO também).

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 são 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 o HTTP, tendem a funcionar melhor com o 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 desempenho médio de espaço / 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.

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

UTF-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 poderiam 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 UTF-16 , que codifica a maioria dos caracteres 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ê precisar se preocupar com caracteres que não podem ser codificados em um único valor 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:

  • O site do consórcio Unicode e, em particular, a seção de tutoriais
  • Artigo de Joel
  • Meu próprio artigo (orientado para .NET)

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 de 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 lhe 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 as regras 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 ‘headers’. 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 

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.

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

Unicode é um padrão que define, juntamente com o ISO / IEC 10646, o Universal Character Set (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 ponto de código ) a cada caractere em seu repertório.

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

Por exemplo,

Caractere UCS = Caractere Unicode Han

Ponto de código UCS = U + 24B62

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

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

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

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

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 é uma 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 (sequências de 8 bits) – bytes. O UTF-8 é uma das várias codificações (methods 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á uma lista ordenada com alguns exemplos randoms .

1. Unicode

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

Então vem 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, por isso não podemos salvar “U + 0024” no computador para o caractere “$”.

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

Então vem methods 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 “$”.

Eu verifiquei os links na resposta do Gumbo, e eu 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ê tem que 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 memory:

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 memory 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 memory 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? … ”

Unicode é 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.

UTF-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.

O UTF-8 foi projetado com estas propriedades em mente:

  • Os caracteres ASCII são codificados exatamente como estão em ASCII, de modo que uma string ASCII também é válida como UTF-8.

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

  • Caracteres fora do intervalo ASCII não usam nenhum byte no intervalo ASCII, 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 bits ou multi-byte raramente será validado como UTF-8.

  • Acesso random: 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.

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

Não, eles não são.


Acho que a primeira sentença da página da Wikipedia que você mencionou 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 formato que um computador pode entender, também conhecido como bits . Em outras palavras, é um caminho / algoritmo para 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 .

UTF-8 é um método para codificar caracteres Unicode usando seqüências de 8 bits.

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