UTF-8, UTF-16 e UTF-32

487

Quais são as diferenças entre UTF-8, UTF-16 e UTF-32?

Entendo que todos eles armazenam Unicode e que cada um usa um número diferente de bytes para representar um caractere. Existe uma vantagem em escolher um sobre o outro?

Peter Mortensen
fonte
36
Assista a este vídeo se você estiver interessado em saber como o Unicode funciona youtube.com/watch?v=MijmeoH9LT4
1
O vídeo se concentra em UTF-8 e, sim, explica bem como a codificação de tamanho variável funciona e é principalmente compatível com computadores que lêem ou gravam apenas ASCII de comprimento fixo. Os caras Unicode foram inteligentes ao projetar a codificação UTF-8.
mins
1
Eu criei uma ferramenta online para conversão e comparação.
Amit Kumar Gupta
1
UTF-8 é o padrão de fato na maioria dos softwares modernos para arquivos salvos . Mais especificamente, é a codificação mais usada para HTML e arquivos de configuração e tradução (o Minecraft, por exemplo, não aceita nenhuma outra codificação para todas as informações de texto). UTF-32 é rápida para a representação de memória interna , e UTF-16 é uma espécie de obsoleto , usado atualmente apenas em Win32 por razões históricas ( UTF-16 era de comprimento fixo quando o Windows 95 foi uma coisa)
Kotauskas
@VladislavToncharov UTF-16 nunca foi uma codificação de comprimento fixo. Você está confundindo com UCS-2.

Respostas:

373

O UTF-8 tem uma vantagem no caso em que os caracteres ASCII representam a maioria dos caracteres em um bloco de texto, porque o UTF-8 os codifica em 8 bits (como o ASCII). Também é vantajoso que um arquivo UTF-8 contendo apenas caracteres ASCII tenha a mesma codificação que um arquivo ASCII.

UTF-16 é melhor onde ASCII não é predominante, pois usa 2 bytes por caractere, principalmente. O UTF-8 começará a usar 3 ou mais bytes para os caracteres de ordem superior, onde o UTF-16 permanece em apenas 2 bytes para a maioria dos caracteres.

UTF-32 cobrirá todos os caracteres possíveis em 4 bytes. Isso o torna bastante inchado. Não consigo pensar em nenhuma vantagem em usá-lo.

AnthonyWJones
fonte
165
Vantagem UTF-32: você não precisa decodificar os dados armazenados no ponto de código Unicode de 32 bits, por exemplo, caractere por manipulação de caracteres. O ponto de código já está disponível no seu array / vetor / string.
richq
22
Também é mais fácil analisar se (o céu o ajuda) você precisa reimplementar a roda.
Paul McMillan
24
Bem, o UTF-8 tem uma vantagem nas transferências de rede - não é necessário se preocupar com o endianness, pois você está transferindo dados um byte de cada vez (em vez de 4).
Tim Čas
30
@richq Você não pode manipular caractere por caractere no UTF-32, pois o ponto do código nem sempre corresponde a um caractere.
Hamstergene
4
UTF-32 vantagem: a manipulação de cadeia é possivelmente mais rápida em comparação com o utf-8 equivalente
Wes
332

Em resumo:

  • UTF-8: codificação de largura variável, compatível com versões anteriores de ASCII. Os caracteres ASCII (U + 0000 a U + 007F) levam 1 byte, os pontos de código U + 0080 a U + 07FF levam 2 bytes, os pontos de código U + 0800 a U + FFFF levam 3 bytes, os pontos de código U + 10000 a U + 10FFFF tome 4 bytes. Bom para texto em inglês, não tão bom para texto asiático.
  • UTF-16: codificação de largura variável. Os pontos de código U + 0000 a U + FFFF levam 2 bytes, os pontos de código U + 10000 a U + 10FFFF levam 4 bytes. Ruim para texto em inglês, bom para texto asiático.
  • UTF-32: codificação de largura fixa. Todos os pontos de código ocupam quatro bytes. Um enorme porco da memória, mas rápido de operar. Raramente usado.

Por muito tempo: consulte Wikipedia: UTF-8 , UTF-16 e UTF-32 .

Adam Rosenfield
fonte
65
@ spurrymoses: estou me referindo estritamente à quantidade de espaço ocupado pelos bytes de dados. UTF-8 requer 3 bytes por caractere asiático, enquanto UTF-16 requer apenas 2 bytes por caractere asiático. Isso realmente não é um grande problema, pois os computadores têm toneladas de memória hoje em dia em comparação com a quantidade média de texto armazenada na memória de um programa.
237 Adam Rosenfield
12
UTF-32 raramente é mais usado ... nos wchar_tpadrões OSX e Linux para 4 bytes. O gcc possui uma opção -fshort-wcharque reduz o tamanho para 2 bytes, mas quebra a compatibilidade binária com as bibliotecas std.
precisa
9
O código fonte @PandaWood UTF-8 pode codificar qualquer caractere! Mas você comparou o requisito de memória com o do UTF-16? Você parece estar perdendo o objetivo!
Ustaman Sangat
16
Se alguém disser que UTF-8 "não é tão bom para texto asiático" no contexto de Todos os formatos de codificação, incluindo aqueles que não podem codificar Unicode, é claro que eles estão errados. Mas esse não é o contexto. O contexto dos requisitos de memória vem do fato de que a pergunta (e a resposta) está comparando UTF-8, UTF-16 e UTF-32, que codificarão o texto asiático, mas usarão quantidades diferentes de memória / armazenamento. Segue-se que sua bondade relativa seria naturalmente inteiramente no contexto dos requisitos de memória. "Não é tão bom"! = "Não é bom".
Paul Gregory
5
@ McGafter: Bem, é claro que existe. Se você deseja confiabilidade, vá direto à boca do cavalo no The Unicode Consortium . Consulte o capítulo 2.5 para obter uma descrição das codificações UTF- *. Mas, para obter uma compreensão simples e de alto nível das codificações, acho que os artigos da Wikipedia são uma fonte muito mais acessível.
Adam Rosenfield
116
  • UTF-8 é variável de 1 a 4 bytes.

  • UTF-16 é variável 2 ou 4 bytes.

  • UTF-32 é fixo em 4 bytes.

Nota: UTF-8 pode levar de 1 a 6 bytes com a convenção mais recente: https://lists.gnu.org/archive/html/help-flex/2005-01/msg00030.html

Quassnoi
fonte
35
UTF8 é realmente 1 a 6 bytes.
Urkle
6
O @Urkle está tecnicamente correto porque o mapeamento de toda a gama de UTF32 / LE / BE inclui U-00200000 - U-7FFFFFFF, mesmo que o Unicode v6.3 termine no U-0010FFFF, inclusive. Aqui está uma boa descrição de como enc / dec de 5 e 6 bytes utf8: lists.gnu.org/archive/html/help-flex/2005-01/msg00030.html
4
fazendo backup deles com partes de referências relevantes e suas fontes?
N611x007
20
@Urkle Não, o UTF-8 não pode ter 5 ou 6 bytes. Os pontos de código Unicode são limitados a 21 bits, o que limita UTF-8 a 4 bytes. (Obviamente, você pode estender o princípio do UTF-8 para codificar números inteiros grandes arbitrários, mas não seria Unicode.) Veja RFC 3629.
rdb
11
Citando Wikipedia: Em novembro de 2003, o UTF-8 foi restringido pelo RFC 3629 para corresponder às restrições da codificação de caracteres UTF-16: proibir explicitamente os pontos de código correspondentes aos caracteres substitutos altos e baixos removeu mais de 3% das seqüências de três bytes e terminando em U + 10FFFF removeu mais de 48% das sequências de quatro bytes e todas as sequências de cinco e seis bytes.
Adam Calvet Bohl
79

O Unicode define um único conjunto enorme de caracteres, atribuindo um valor inteiro único a cada símbolo gráfico (que é uma grande simplificação e não é verdade, mas é suficientemente próximo para os fins desta pergunta). UTF-8/16/32 são simplesmente maneiras diferentes de codificar isso.

Em resumo, o UTF-32 usa valores de 32 bits para cada caractere. Isso permite que eles usem um código de largura fixa para cada caractere.

O UTF-16 usa 16 bits por padrão, mas isso fornece apenas 65k caracteres possíveis, o que não é nem o suficiente para o conjunto Unicode completo. Portanto, alguns caracteres usam pares de valores de 16 bits.

E o UTF-8 usa valores de 8 bits por padrão, o que significa que os 127 primeiros valores são caracteres de byte único de largura fixa (o bit mais significativo é usado para significar que este é o início de uma sequência de bytes múltiplos, deixando 7 bits para o valor real dos caracteres). Todos os outros caracteres são codificados como sequências de até 4 bytes (se a memória servir).

E isso nos leva às vantagens. Qualquer caractere ASCII é diretamente compatível com o UTF-8, portanto, para atualizar aplicativos herdados, o UTF-8 é uma escolha comum e óbvia. Em quase todos os casos, também utilizará menos memória. Por outro lado, você não pode garantir a largura de um personagem. Pode ter 1, 2, 3 ou 4 caracteres de largura, o que dificulta a manipulação das cordas.

O UTF-32 é o oposto, ele usa mais memória (cada caractere tem uma largura fixa de 4 bytes), mas por outro lado, você sabe que todo caractere tem esse comprimento preciso, portanto a manipulação de strings se torna muito mais simples. Você pode calcular o número de caracteres em uma sequência simplesmente a partir do comprimento em bytes da sequência. Você não pode fazer isso com UTF-8.

UTF-16 é um compromisso. Ele permite que a maioria dos caracteres caiba em um valor de 16 bits de largura fixa. Portanto, contanto que você não possua símbolos chineses, notas musicais ou outros, você pode assumir que cada caractere tem 16 bits de largura. Ele usa menos memória que UTF-32. Mas, de certa forma, é "o pior dos dois mundos". Ele quase sempre usa mais memória que o UTF-8 e ainda não evita o problema que afeta o UTF-8 (caracteres de tamanho variável).

Por fim, muitas vezes é útil apenas seguir o que a plataforma suporta. O Windows usa UTF-16 internamente, portanto, no Windows, essa é a escolha óbvia.

O Linux varia um pouco, mas geralmente eles usam UTF-8 para tudo que é compatível com Unicode.

Resposta tão curta: Todas as três codificações podem codificar o mesmo conjunto de caracteres, mas representam cada caractere como sequências de bytes diferentes.

jalf
fonte
12
É impreciso dizer que o Unicode atribui um número inteiro exclusivo a cada símbolo gráfico . Ele atribui esse valor a cada ponto de código, mas alguns pontos de código são caracteres de controle invisíveis e alguns símbolos gráficos requerem vários pontos de código para representar.
tchrist
15
@ Chris: Sim, é impreciso. O problema é que, para explicar com precisão o Unicode, você precisa escrever milhares de páginas. Eu esperava para obter o conceito básico em toda a explicar a diferença entre codificações
jalf
@jalf lol direito então basicamente para explicar Unicode você teria que escrever o Unicode Core Specification
Justin Ohms
@tchrist Mais especificamente, você pode construir símbolos chineses a partir das primitivas fornecidas (mas elas estão no mesmo gráfico, então você acaba usando uma quantidade irreal de espaço - disco ou RAM - para codificá-las) em vez de usar o embutidos.
Kotauskas 29/05/19
44

Unicode é um padrão e você pode pensar em UTF-x como uma implementação técnica para alguns propósitos práticos:

  • UTF-8 - " tamanho otimizado ": mais adequado para dados baseados em caracteres latinos (ou ASCII), são necessários apenas 1 byte por caractere, mas o tamanho aumenta de acordo com a variedade de símbolos (e, na pior das hipóteses, pode crescer até 6 bytes por caractere)
  • UTF-16 - " balance ": são necessários no mínimo 2 bytes por caractere, o que é suficiente para o conjunto existente dos idiomas principais com tamanho fixo para facilitar o manuseio de caracteres (mas o tamanho ainda é variável e pode crescer até 4 bytes por caractere )
  • UTF-32 - " performance ": permite o uso de algoritmos simples como resultado de caracteres de tamanho fixo (4 bytes), mas com desvantagem de memória
torre
fonte
«Línguas tradicionais» não que dominante em muitos partes do mundo ^^
tuxayo
2
O UTF-16 é realmente otimizado para tamanho para caracteres não ASCII. Pois depende realmente de quais idiomas será usado.
tuxayo
@tuxayo concordo totalmente, vale a pena notar conjuntos de caracteres Hanzi e Kanji para a parte asiática do mundo.
rook
Deve ser a melhor resposta. Isso é correto demais para ser enterrado aqui.
Michal Štein
28

Eu tentei dar uma explicação simples no meu blog .

UTF-32

requer 32 bits (4 bytes) para codificar qualquer caractere. Por exemplo, para representar o ponto de código do caractere "A" usando esse esquema, você precisará escrever 65 no número binário de 32 bits:

00000000 00000000 00000000 01000001 (Big Endian)

Se você olhar mais de perto, notará que os sete bits mais à direita são na verdade os mesmos bits ao usar o esquema ASCII. Mas como o UTF-32 é um esquema de largura fixa , devemos anexar três bytes adicionais. Significando que se tivermos dois arquivos que contêm apenas o caractere "A", um é codificado em ASCII e o outro é codificado em UTF-32, o tamanho será de 1 byte e 4 bytes, respectivamente.

UTF-16

Muitas pessoas pensam que, como o UTF-32 usa largura fixa de 32 bits para representar um ponto de código, o UTF-16 tem 16 bits de largura fixa. ERRADO!

Em UTF-16, o ponto de código pode ser representado em 16 bits ou em 32 bits. Portanto, esse esquema é um sistema de codificação de comprimento variável. Qual é a vantagem sobre o UTF-32? Pelo menos para ASCII, o tamanho dos arquivos não será 4 vezes o original (mas ainda duas vezes), portanto, ainda não somos compatíveis com versões anteriores do ASCII.

Como 7 bits são suficientes para representar o caractere "A", agora podemos usar 2 bytes em vez de 4 como o UTF-32. Será parecido com:

00000000 01000001

UTF-8

Você adivinhou certo. No UTF-8, o ponto de código pode ser representado usando 32, 16, 24 ou 8 bits e, como sistema UTF-16, este também é um sistema de codificação de comprimento variável.

Finalmente, podemos representar "A" da mesma maneira que representamos usando o sistema de codificação ASCII:

01001101

Um pequeno exemplo em que UTF-16 é realmente melhor que UTF-8:

Considere a letra chinesa "語" - sua codificação UTF-8 é:

11101000 10101010 10011110

Embora sua codificação UTF-16 seja mais curta:

10001010 10011110

Para entender a representação e como ela é interpretada, visite a postagem original.

Maroun
fonte
19

UTF-8

  • não tem conceito de ordem de bytes
  • usa entre 1 e 4 bytes por caractere
  • ASCII é um subconjunto compatível de codificação
  • completamente auto-sincronizado, por exemplo, um byte descartado de qualquer lugar em um fluxo corromperá no máximo um único caractere
  • praticamente todos os idiomas europeus são codificados em dois bytes ou menos por caractere

UTF-16

  • deve ser analisado com a ordem de bytes conhecida ou com a leitura de uma marca de ordem de byte (BOM)
  • usa 2 ou 4 bytes por caractere

UTF-32

  • cada caractere tem 4 bytes
  • deve ser analisado com a ordem de bytes conhecida ou com a leitura de uma marca de ordem de byte (BOM)

O UTF-8 será o mais eficiente em espaço, a menos que a maioria dos caracteres seja do espaço de caracteres CJK (chinês, japonês e coreano).

UTF-32 é melhor para acesso aleatório por deslocamento de caracteres em uma matriz de bytes.

Jeff Adamson
fonte
Como a "sincronização automática" funciona no UTF-8? Você pode dar exemplos para caracteres de 1 e 2 bytes?
Koray Tugay
2
@KorayTugay Seqüências de bytes mais curtas válidas nunca são usadas em caracteres mais longos. Por exemplo, ASCII está no intervalo de 0 a 127, o que significa que todos os caracteres de um byte têm o formato 0xxxxxxxbinário. Todos os caracteres de dois bytes começam 110xxxxxcom um segundo byte de 10xxxxxx. Então, digamos que o primeiro caractere de um caractere de dois bytes seja perdido. Assim que vir 10xxxxxxsem um precedente 110xxxxxx, você pode determinar com certeza que um byte foi perdido ou corrompido e descartar esse caractere (ou solicitá-lo novamente de um servidor ou qualquer outra coisa) e seguir em frente até ver um primeiro byte válido novamente .
Chris
1
se você tiver o deslocamento para um caractere, terá o deslocamento para esse caractere - utf8, utf16 ou utf32 funcionará da mesma forma nesse caso; isto é, todos são igualmente bons no acesso aleatório por deslocamento de caracteres em uma matriz de bytes. A idéia de que utf32 é melhor na contagem de caracteres que utf8 também é completamente falsa. Um ponto de código (que não é o mesmo que um caractere que, novamente, não é o mesmo que um grafema .. suspiro) tem 32 bits de largura no utf32 e entre 8 e 32 bits no utf8, mas um caractere pode abranger vários pontos de código, o que destrói a grande vantagem que as pessoas afirmam que o utf32 possui sobre o utf8.
Clearer
14

Fiz alguns testes para comparar o desempenho do banco de dados entre o UTF-8 e o UTF-16 no MySQL.

Velocidades de atualização

UTF-8

Digite a descrição da imagem aqui

UTF-16

Digite a descrição da imagem aqui

Inserir velocidades

Digite a descrição da imagem aqui

Digite a descrição da imagem aqui

Excluir velocidades

Digite a descrição da imagem aqui

Digite a descrição da imagem aqui

Farid Movsumov
fonte
14

No UTF-32, todos os caracteres são codificados com 32 bits. A vantagem é que você pode calcular facilmente o comprimento da string. A desvantagem é que, para cada caractere ASCII, você perde mais três bytes.

Nos caracteres UTF-8, o comprimento é variável, os caracteres ASCII são codificados em um byte (oito bits), a maioria dos caracteres especiais ocidentais são codificados em dois bytes ou três bytes (por exemplo, € é três bytes) e caracteres mais exóticos podem ser usados. para quatro bytes. Uma clara desvantagem é que, a priori, você não pode calcular o comprimento da string. Mas são necessários muito menos bytes para codificar o texto do alfabeto latino (inglês), comparado ao UTF-32.

UTF-16 também é de comprimento variável. Os caracteres são codificados em dois ou quatro bytes. Eu realmente não vejo o ponto. Tem a desvantagem de ter tamanho variável, mas não tem a vantagem de economizar tanto espaço quanto o UTF-8.

Desses três, claramente o UTF-8 é o mais difundido.

vartec
fonte
Por que eu gostaria de calcular o comprimento da string durante o desenvolvimento de sites? Existe alguma vantagem em escolher UTF-8 / UTF-16 no desenvolvimento web?
Morfidon 8/09/17
"A vantagem é que você pode calcular facilmente o comprimento da string". Se você definir o comprimento pelo número de pontos de código, sim, poderá dividir o comprimento do byte por 4 para obtê-lo com o UTF-32. Entretanto, essa não é uma definição muito útil: ela pode não estar relacionada ao número de caracteres. Além disso, a normalização pode alterar o número de pontos de código na string. Por exemplo, a palavra francesa "été" pode ser codificada de pelo menos 4 maneiras diferentes, com três comprimentos de ponto de código distintos.
O UTF-16 é possivelmente mais rápido que o UTF-8 e também não desperdiça memória como o UTF-32.
Michal Štein
6

Dependendo do seu ambiente de desenvolvimento, você pode nem ter a escolha de qual codificação seu tipo de dados de cadeia usará internamente.

Mas para armazenar e trocar dados, eu sempre usaria o UTF-8, se você tiver a opção. Se você tiver principalmente dados ASCII, isso fornecerá a menor quantidade de dados a ser transferida, enquanto ainda é possível codificar tudo. Otimizar para o mínimo de E / S é o caminho a seguir em máquinas modernas.

mghie
fonte
Indiscutivelmente, muito mais importante do que os requisitos de espaço é o fato de que o UTF-8 é imune à resistência. UTF-16 e UTF-32 inevitavelmente terão que lidar com questões de endianness, onde UTF-8 é simplesmente um fluxo de octetos.
2nspectable IInspectable
2

Como mencionado, a diferença é principalmente o tamanho das variáveis ​​subjacentes, que em cada caso aumentam para permitir a representação de mais caracteres.

No entanto, fontes, codificação e outras coisas são incrivelmente complicadas (desnecessariamente?), Portanto, é necessário um grande link para preencher mais detalhes:

http://www.cs.tut.fi/~jkorpela/chars.html#ascii

Não espere entender tudo, mas se você não quiser ter problemas mais tarde, vale a pena aprender o máximo que puder, o mais cedo possível (ou apenas pedir a alguém que resolva isso por você).

Paulo.

Paul W Homer
fonte
ou apenas use UTF-8 como padrão, pois se tornou o padrão de fato e descubra se um novo sistema suporta ou não. caso contrário, você pode voltar a esta postagem.
robotik 28/02
-2

Em resumo, o único motivo para usar UTF-16 ou UTF-32 é oferecer suporte a scripts antigos e não em inglês, respectivamente.

Fiquei me perguntando por que alguém escolheria ter codificação não-UTF-8 quando é obviamente mais eficiente para fins de programação / web.

Um equívoco comum - o número com sufixo NÃO é uma indicação de sua capacidade. Todos eles suportam o Unicode completo, apenas que o UTF-8 pode lidar com ASCII com um único byte, portanto, é MAIS eficiente / menos corrompível para a CPU e pela Internet.

Algumas boas leituras: http://www.personal.psu.edu/ejp10/blogs/gotunicode/2007/10/which_utf_do_i_use.html e http://utf8everywhere.org

killjoy
fonte
Não sei por que você sugere que o uso de UTF-16 ou UTF-32 seja compatível com texto em inglês. UTF-8 pode lidar com isso muito bem. E há caracteres não ASCII no texto em inglês também. Como um não marceneiro de largura zero. Ou um traço em. Receio que esta resposta não agregue muito valor.
#
Esta questão está sujeita a votação decrescente porque o UTF-8 ainda é comumente usado em arquivos HTML, mesmo que a maioria dos caracteres seja de 3 bytes no UTF-8,
#:
O suporte do @IInspectable não é o melhor texto, promove ou melhor suporte seria mais preciso
robotik 28/02
Enviar uma página como utf8everywhere.org não é o que eu faria em uma resposta SO.
Michal Štein