A largura fixa ou variável é UTF-16? Por que o UTF-8 não tem problema de ordem de bytes?

15
  1. A largura fixa ou variável é UTF-16? Eu tenho resultados diferentes de diferentes fontes:

    De link :

    UTF-16 stores Unicode characters in sixteen-bit chunks.

    De link :

    UTF-16 (16-bit Unicode Transformation Format) is a character encoding for Unicode capable of encoding 1,112,064[1] numbers (called code points) in the Unicode code space from 0 to 0x10FFFF. It produces a variable-length result of either one or two 16-bit code units per code point.

  2. Da primeira fonte

    UTF-8 also has the advantage that the unit of encoding is the byte, so there are no byte-ordering issues.

    Por que o UTF-8 não tem problema de ordem de bytes? É de largura variável e um caractere pode conter mais de um byte, então eu acho que o byte-order ainda pode ser um problema?

Obrigado e cumprimentos!

    
por Tim 23.07.2011 / 01:45
fonte

2 respostas

12

(1) What does byte sequence mean, an arrary of char in C? Is UTF-16 a byte sequence, or what is it then? (2) Why does a byte sequence have nothing to do with variable length?

Você parece estar entendendo mal quais são os problemas endianos. Aqui está um breve resumo.

Um inteiro de 32 bits ocupa 4 bytes. Agora, sabemos a ordem lógica desses bytes. Se você tem um inteiro de 32 bits, você pode obter o alto byte com o seguinte código:

uint32_t value = 0x8100FF32;
uint8_t highByte = (uint8_t)((value >> 24) & 0xFF); //Now contains 0x81

Tudo isso é bom e bom. Onde o problema começa é como vários armazenamentos de hardware e recupera inteiros da memória.

Na ordem Big Endian, uma parte de 4 bytes de memória que você lê como um inteiro de 32 bits será lida com o primeiro byte sendo o byte alto:

[0][1][2][3]

Na ordem de Little Endian, uma parte de 4 bytes de memória que você lê como um inteiro de 32 bits será lida com o primeiro byte sendo o byte baixo :

[3][2][1][0]

Se você tiver um ponteiro para um ponteiro para um valor de 32 bits, poderá fazer isso:

uint32_t value = 0x8100FF32;
uint32_t *pValue = &value;
uint8_t *pHighByte = (uint8_t*)pValue;
uint8_t highByte = pHighByte[0]; //Now contains... ?

De acordo com o C / C ++, o resultado disso é indefinido. Pode ser 0x81. Ou pode ser 0x32. Tecnicamente, ele poderia retornar qualquer coisa, mas para sistemas reais, ele retornaria um ou outro.

Se você tiver um ponteiro para um endereço de memória, poderá ler esse endereço como um valor de 32 bits, um valor de 16 bits ou um valor de 8 bits. Em uma máquina big endian, o ponteiro aponta para o byte alto; em uma pequena máquina endian, o ponteiro aponta para o byte baixo.

Note que isso é tudo sobre leitura e gravação de / para a memória. Ele tem nada para fazer com o código C / C ++ interno. A primeira versão do código, a que o C / C ++ não declara como indefinida, irá sempre funcionar para obter o byte alto.

O problema é quando você começa a ler os fluxos de bytes. Tal como de um arquivo.

Valores de 16 bits têm os mesmos problemas que os de 32 bits; eles têm apenas 2 bytes em vez de 4. Portanto, um arquivo pode conter valores de 16 bits armazenados em ordem big endian ou little endian.

O UTF-16 é definido como uma sequência de valores de 16 bits . Efetivamente, é um uint16_t[] . Cada unidade de código individual é um valor de 16 bits. Portanto, para carregar corretamente o UTF-16, você deve saber qual é o valor final dos dados.

O UTF-8 é definido como uma sequência de valores de 8 bits . É um uint8_t[] . Cada unidade de código individual tem 8 bits de tamanho: um único byte.

Agora, tanto o UTF-16 quanto o UTF-8 permitem que várias unidades de código (valores de 16 ou 8 bits) sejam combinadas para formar um ponto de código Unicode (um "caractere", mas isso não é o termo correto; é uma simplificação). A ordem dessas unidades de código que formam um codepoint é ditada pelas codificações UTF-16 e UTF-8.

Ao processar UTF-16, você lê um valor de 16 bits, fazendo qualquer conversão endian necessária. Então, você detecta se é um par substituto; se estiver, você lê outro valor de 16 bits, combina os dois e, a partir disso, obtém o valor do ponto de código Unicode.

Ao processar UTF-8, você lê um valor de 8 bits. Nenhuma conversão endian é possível, já que existe apenas um byte. Se o primeiro byte denota uma seqüência de múltiplos bytes, você lê um certo número de bytes, conforme determinado pela seqüência de múltiplos bytes. Cada byte individual é um byte e, portanto, não possui conversão endian. A ordem desses bytes na sequência, assim como a ordem dos pares substitutos em UTF-16, é definida por UTF-8.

Portanto, não pode haver problemas endian com o UTF-8.

    
por 24.07.2011 / 02:00
fonte
10

A resposta de Jeremy Banks está correta até o momento, mas não abordou o pedido de bytes.

Quando você usa UTF-16, a maioria dos glifos são armazenados usando uma palavra de dois bytes - mas quando a palavra é armazenada em um arquivo de disco, que ordem você usa para armazenar os bytes constituintes?

Como exemplo, o glifo CJK (chinês) da palavra "water" tem uma codificação UTF-16 em hexadecimal de 6C34. Quando você escreve isso como dois bytes em disco, você escreve como "big-endian" (os dois bytes são 6C 34)? Ou você escreve como "little-endian (os dois bytes são 34 6C)?

Com UTF-16, ambas as ordenações são legítimas, e você geralmente indica qual delas o arquivo possui, tornando a primeira palavra no arquivo uma Byte Order Mark (BOM), que para codificação big endian é FE FF e para codificação little-endian é FF FE.

O UTF-32 tem o mesmo problema e a mesma solução.

O UTF-8 não tem esse problema, porque é de comprimento variável e você efetivamente escreve uma sequência de bytes de glifos como se fosse little-endian. Por exemplo, a letra "P" é sempre codificada usando um byte - 80 - e o caractere de substituição é sempre codificado usando os dois bytes FF FD nessa ordem.

Alguns programas colocam um indicador de três bytes (EF BB BF) no início de um arquivo UTF-8, e isso ajuda a distinguir UTF-8 de codificações semelhantes como ASCII, mas isso não é muito comum, exceto no MS Windows. / p>     

por 23.07.2011 / 02:29
fonte