Por que o UTF-8 desperdiça vários bits em sua codificação


17

De acordo com o artigo da Wikipedia , UTF-8 tem este formato:

Primeiro código Último código Bytes Byte 1 Byte 2 Byte 3 Byte 4
point point Usado
U + 0000 U + 007F 1 0xxxxxxx
U + 0080 U + 07FF 2 110xxxxx 10xxxxxx
U + 0800 U + FFFF 3 1110xxxx 10xxxxxx 10xxxxxx
U + 10000 U + 1FFFFF 4 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
x significa que este bit é usado para selecionar o ponto de código.

Isso desperdiça dois bits em cada byte de continuação e um bit no primeiro byte. Por que o UTF-8 não é codificado da seguinte maneira?

Primeiro código Último código Bytes Byte 1 Byte 2 Byte 3
point point Usado
U + 0000 U + 007F 1 0xxxxxxx
U + 0080 U + 3FFF 2 10xxxxxx xxxxxxxx
U + 0800 U + 1FFFFF 3 110xxxxx xxxxxxxx xxxxxxxx

Ele economizaria um byte quando o ponto de código estiver fora do plano multilíngue básico ou se o ponto de código estiver no intervalo [U + 800, U + 3FFF].

Por que o UTF-8 não é codificado de maneira mais eficiente?


3
cl.cam.ac.uk/~mgk25/ucs/utf-8-history.txt Sua codificação proposta é semelhante à proposta FSS / UTF original. Ken Thompson e Rob Pike queriam a propriedade de auto-sincronização.
Ninjalj 9/03

4
Além disso, sua codificação parece não garantir que os valores do código ASCII não apareçam em nenhuma parte da representação para caracteres não ASCII. O FSS / UTF e o UTF-8 foram projetados para trabalhar com programas herdados (por exemplo: aqueles que usam ASCII NUL e barra (separador de caminho) como separadores).
Ninjalj 9/03

Respostas:


26

Isso é feito para que você possa detectar quando está no meio de uma sequência de vários bytes. Ao analisar dados UTF-8, você sabe que, se vir 10xxxxxx, está no meio de um caractere multibyte e deve fazer backup no fluxo até ver um 0xxxxxxou outro 11xxxxxx. Usando seu esquema, os bytes 2 ou 3 podem acabar facilmente com padrões como um 0xxxxxxxou outro11xxxxxx

Lembre-se também de que a quantidade economizada varia inteiramente de acordo com o tipo de dados que você está codificando. Para a maioria dos textos, mesmo os asiáticos, você raramente vê caracteres de quatro bytes com texto normal. Além disso, as estimativas ingênuas das pessoas sobre a aparência do texto geralmente estão erradas. Eu tenho um texto localizado para UTF-8 que inclui seqüências de caracteres japonesas, chinesas e coreanas, mas é realmente o russo que ocupa mais espaço. (Como nossas seqüências de caracteres asiáticas geralmente têm caracteres romanos intercalados por nomes próprios, pontuação e outros, e porque a palavra média chinesa é de 1 a 3 caracteres, enquanto a palavra média russa é muito, muito mais.)


Mas, com o meu esquema, se você começar em um local que se sabe estar no início de um caractere, poderá dizer quantos bytes existem no caractere e chegar ao início do próximo caractere.
Qbt937

11
Certo. Seu esquema é mais denso em informações, mas não possui um recurso importante que o UTF-8 fornece. Em geral, as pessoas preferem a segurança, e é por isso que o UTF-8 é possível. Além disso, para provar realmente que seu esquema é realmente mais eficiente, você deseja fornecer estatísticas usando texto real. Você pode achar que, na maioria dos textos reais, seu esquema economiza uma quantia muito trivial e, portanto, a economia não vale a pena.
Gort the Robot

3
Uma outra característica importante: se não houver nenhum ponto de código zero incorporado, não haverá zeros incorporados na string.
Deduplicator

Para scripts em tailandês, é necessário permitir 4 bytes por caractere impresso. Eles não apenas chegaram atrasados ​​à festa e também obtiveram um grupo de códigos numerado. Muitas coisas que parecem um único caractere quando impressas são realmente compostas por três caracteres unicode diferentes.
James Anderson

@ qbt937: Usando seu esquema, como uma varredura seria rápida para descobrir se uma string contém outra?
precisa

6

A maneira oficial permite que o decodificador saiba quando está no meio da tupla e sabe pular bytes (ou retroceder) até que o byte comece com 0ou 11; isso evita valores de lixo quando um único byte é corrompido.


3

Resposta curta, sua proposta não diferencia entre o primeiro byte e os bytes de continuação.

O padrão de bits na extremidade superior do primeiro byte informa com quantos bytes o caractere real é criado. Esses padrões também fornecem algum reconhecimento de erro ao analisar uma string. Se você está lendo o (aparentemente) primeiro byte de um personagem e obtém 10xxxxxx, sabe que está fora de sincronia.


2

O que não foi mencionado é que, se você possui uma sequência correta de pontos de código e um ponteiro que é garantido para apontar para o primeiro byte de um ponto de código, com UTF-8, é possível encontrar facilmente o ponteiro para o primeiro byte do ponto de código anterior (pule todos os bytes que começam com 01xx xxxx). Com sua codificação, é impossível sem examinar potencialmente todos os bytes até o início da string.

Considere as seqüências de (2n + 2) bytes

0xxxxxxx
n times (10xxxxxx, 10xxxxxx)
0xxxxxxx

e

n times (10xxxxxx, 10xxxxxx)
(10xxxxxx, 0xxxxxxx)

Se você tiver um ponteiro para o primeiro byte do primeiro ponto de código após esta sequência, deverá examinar todos os bytes para descobrir se o último ponto de código é 0xxxxxxx ou (10xxxxxx, 0xxxxxxx).

Na verdade, existem esquemas de codificação mais eficientes, nos quais o acesso ao ponto de código anterior pode ser feito em tempo constante e os ponteiros para o meio de um ponto de código podem ser corrigidos. Permita os seguintes códigos:

X where X < 128
YX where 128 ≤ Y < 236, X < 128
ZYY where 236 ≤ Z < 256, 0 ≤ Y < 236. 

Se um dos três bytes anteriores for ≥ 236, será o início de uma sequência de 3 bytes, porque não pode haver dois bytes dentro de qualquer sequência válida de 3 bytes. Caso contrário, se um dos dois bytes anteriores for ≥ 128, será o início de uma sequência de dois bytes. Caso contrário, o byte anterior é um byte único <128.

Procurar uma substring se torna um pouco mais difícil. Você pode excluir zero bytes para que uma string contenha apenas um byte zero se contiver um ponto de código zero.


O que não foi mencionado ... - não é exatamente isso que se segue diretamente da observação feita na resposta do @ratchet freak.
Piotr Dobrogost 01/03/19
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.