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?
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?
Respostas:
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.
Em resumo:
Por muito tempo: consulte Wikipedia: UTF-8 , UTF-16 e UTF-32 .
wchar_t
padrões OSX e Linux para 4 bytes. O gcc possui uma opção -fshort-wchar
que reduz o tamanho para 2 bytes, mas quebra a compatibilidade binária com as bibliotecas std.
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
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.
Unicode é um padrão e você pode pensar em UTF-x como uma implementação técnica para alguns propósitos práticos:
Eu tentei dar uma explicação simples no meu blog .
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.
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
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
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.
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.
0xxxxxxx
binário. Todos os caracteres de dois bytes começam 110xxxxx
com um segundo byte de 10xxxxxx
. Então, digamos que o primeiro caractere de um caractere de dois bytes seja perdido. Assim que vir 10xxxxxx
sem 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 .
Fiz alguns testes para comparar o desempenho do banco de dados entre o UTF-8 e o UTF-16 no MySQL.
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.
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.
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.
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