it-swarm.dev

Diferença entre UTF-8 e UTF-16?

Diferença entre UTF-8 e UTF-16? Por que precisamos disso?

MessageDigest md = MessageDigest.getInstance("SHA-256");
String text = "This is some text";

md.update(text.getBytes("UTF-8")); // Change this to "UTF-16" if needed
byte[] digest = md.digest();
130
theJava

Acredito que há muitos bons artigos sobre isso na Web, mas aqui está um breve resumo.

Tanto o UTF-8 quanto o UTF-16 são codificações de comprimento variável. No entanto, em UTF-8, um caractere pode ocupar um mínimo de 8 bits, enquanto que em UTF-16, o comprimento de caractere começa com 16 bits.

Principais UTF-8 pros:

  • Caracteres básicos ASCII como dígitos, caracteres latinos sem acentos, etc. ocupam um byte que é idêntico à representação US-ASCII. Desta forma, todas as strings US-ASCII tornam-se válidas UTF-8, o que fornece compatibilidade com versões anteriores decentes em muitos casos.
  • Nenhum byte nulo, que permite usar sequências terminadas em null, isso também apresenta uma grande compatibilidade retroativa.
  • O UTF-8 é independente da ordem dos bytes, então você não precisa se preocupar com o problema Big Endian/Little Endian.

Principais UTF-8 contras:

  • Muitos caracteres comuns têm comprimentos diferentes, o que retarda a indexação por codepoint e o cálculo de um codepoint conta terrivelmente.
  • Mesmo que a ordem de bytes não importe, às vezes o UTF-8 ainda tem BOM (byte order mark) que serve para notificar que o texto está codificado em UTF-8, e também quebra a compatibilidade com o softwareASCII mesmo se o texto contém apenas ASCII caracteres. O software da Microsoft (como o Bloco de Notas) gosta especialmente de adicionar a BOM ao UTF-8.

Principais UTF-16 pros:

  • BMP (básico multilingue avião) caracteres, incluindo latim, cirílico, a maioria dos chineses (o PRC fez suporte para alguns códigos de código fora BMP obrigatório), a maioria dos japoneses podem ser representados com 2 bytes. Isso acelera a indexação e o cálculo da contagem de pontos de código no caso de o texto não conter caracteres suplementares.
  • Mesmo que o texto tenha caracteres suplementares, eles ainda são representados por pares de valores de 16 bits, o que significa que o comprimento total ainda é divisível por dois e permite usar o char de 16 bits como o componente primitivo da string.

Principais UTF-16 contras:

  • Muitos bytes nulos em strings US-ASCII, o que significa que não há sequências terminadas em null e muita memória desperdiçada.
  • Usá-lo como uma codificação de comprimento fixo "funciona principalmente" em muitos cenários comuns (especialmente nos EUA/UE/países com alfabetos cirílicos/Israel/países árabes/Irã e muitos outros), muitas vezes levando a suporte quebrado onde isso não acontece. Isso significa que os programadores precisam estar cientes dos pares substitutos e lidar com eles adequadamente nos casos em que isso é importante!
  • Seu tamanho é variável, portanto, contar ou indexar pontos de código é caro, embora seja menor que UTF-8.

Em geral, UTF-16 é geralmente melhor para representação na memória porque BE/LE é irrelevante lá (apenas use a ordem nativa) e a indexação é mais rápida (apenas não se esqueça de manipular corretamente os pares substitutos). O UTF-8, por outro lado, é extremamente bom para arquivos de texto e protocolos de rede, porque não há problema BE/LE e a terminação nula geralmente é útil, assim como a compatibilidade com ASCII.

275
Sergei Tachenov

Eles são simplesmente esquemas diferentes para representar caracteres Unicode.

Ambos são de comprimento variável - o UTF-16 usa 2 bytes para todos os caracteres no plano multilingue básico (BMP), que contém a maioria dos caracteres de uso comum.

O UTF-8 usa entre 1 e 3 bytes para caracteres no BMP, até 4 para caracteres no intervalo Unicode atual de U + 0000 para U + 1FFFFF e é extensível até U + 7FFFFFFF se isso for necessário ... mas notavelmente todos os caracteres ASCII são representados em um único byte cada.

Para os propósitos de um resumo da mensagem, não importa qual desses você escolher, contanto que todos que tentarem recriar o resumo usem a mesma opção.

Veja esta página para mais informações sobre UTF-8 e Unicode.

(Observe que todos os caracteres Java são pontos de código UTF-16 dentro do BMP; para representar caracteres acima de U + FFFF, é necessário usar pares substitutos em Java.)

18
Jon Skeet

Isso não está relacionado ao UTF-8/16 (em geral, embora ele converta para UTF16 e a parte BE/LE possa ser definida com uma única linha), mas abaixo está a maneira mais rápida de converter String em byte []. Por exemplo: bom exatamente para o caso fornecido (código hash). String.getBytes (enc) é relativamente lento.

static byte[] toBytes(String s){
        byte[] b=new byte[s.length()*2];
        ByteBuffer.wrap(b).asCharBuffer().put(s);
        return b;
    }
4
bestsss

Segurança: Use apenas UTF-8

Diferença entre UTF-8 e UTF-16? Por que precisamos disso?

Houve pelo menos um par de vulnerabilidades de segurança em implementações de TF-16 . Veja Wikipedia para detalhes .

WHATWG e W3C tem agora declarado que somente TF-8 é para ser usado na web.

Os problemas [de segurança] descritos aqui desaparecem quando usamos exclusivamente o UTF-8, que é uma das muitas razões que agora é a codificação obrigatória para todas as coisas.

Outros grupos estão dizendo o mesmo.

Assim, enquanto o UTF-16 pode continuar sendo usado internamente por alguns sistemas como Java e Windows, o pouco uso de UTF-16 que você possa ter visto no passado para arquivos de dados, troca de dados e outros provavelmente desaparecerá completamente.

0
Basil Bourque