¿Por qué UTF-8 desperdicia varios bits en su codificación?

13

Según el artículo de Wikipedia , UTF-8 tiene este formato:

First code Last code Bytes Byte 1    Byte 2    Byte 3    Byte 4
point      point     Used
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 means that this bit is used to select the code point.

Esto desperdicia dos bits en cada byte de continuación y un bit en el primer byte. ¿Por qué UTF-8 no está codificado como el siguiente?

First code Last code Bytes Byte 1    Byte 2    Byte 3
point      point     Used
U+0000     U+007F    1     0xxxxxxx
U+0080     U+3FFF    2     10xxxxxx  xxxxxxxx
U+0800     U+1FFFFF  3     110xxxxx  xxxxxxxx  xxxxxxxx

Se ahorraría un byte cuando el punto de código está fuera del plano multilingüe básico o si el punto de código está dentro del rango [U + 800, U + 3FFF].

¿Por qué UTF-8 no está codificado de una manera más eficiente?

    
pregunta qbt937 09.11.2014 - 20:50

5 respuestas

24

Esto se hace para que pueda detectar cuándo se encuentra en medio de una secuencia de múltiples bytes. Cuando observa los datos de UTF-8, sabe que si ve 10xxxxxx , está en medio de un carácter multibyte, y debería realizar una copia de seguridad en la secuencia hasta que vea 0xxxxxx o 11xxxxxx . Usando tu esquema, los bytes 2 o 3 podrían fácilmente terminar con patrones como 0xxxxxxx o 11xxxxxx

También tenga en cuenta que la cantidad que se guarda varía completamente en qué tipo de datos de cadena está codificando. Para la mayoría de los textos, incluso los asiáticos, rara vez verá caracteres de cuatro bytes con texto normal. Además, las estimaciones ingenuas de las personas sobre el aspecto del texto a menudo son erróneas. Tengo texto localizado para UTF-8 que incluye cadenas japonesas, chinas y coreanas, pero en realidad es el ruso el que ocupa más espacio. (Debido a que nuestras cadenas asiáticas a menudo tienen caracteres romanos intercalados con nombres propios, signos de puntuación y demás) y porque la palabra china promedio es de 1-3 caracteres, mientras que la palabra rusa promedio es muchas, muchas más.)

    
respondido por el Steven Burnap 09.11.2014 - 20:56
5

La forma oficial le permite al decodificador saber cuando está en la mitad de la tupla y sabe omitir bytes (o retroceder) hasta que el byte comience con 0 o 11 ; esto evita los valores de basura cuando un solo byte se corrompe.

    
respondido por el ratchet freak 09.11.2014 - 20:55
2

Respuesta corta, su propuesta no diferencia entre el primer byte y los bytes de continuación.

El patrón de bits en el extremo superior del primer byte le indica con cuántos bytes se construye el carácter real. Estos patrones también proporcionan algún reconocimiento de error al analizar una cadena. Si estás leyendo el primer byte (aparentemente) de un personaje y obtienes 10xxxxxx, entonces sabes que no estás sincronizado.

    
respondido por el Kitana 09.11.2014 - 21:25
2

Lo que no se ha mencionado es que si tiene una secuencia correcta de puntos de código y un puntero que garantiza apuntar al primer byte de un punto de código, con UTF-8 puede encontrar fácilmente el puntero para el primer byte del punto de código anterior (omita todos los bytes que comiencen con 01xx xxxx). Con su codificación, es imposible sin examinar potencialmente todos los bytes hasta el inicio de la cadena.

Considere las secuencias de (2n + 2) bytes

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

y

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

Si tiene un puntero al primer byte del primer punto de código después de esta secuencia, debe examinar todos bytes para averiguar si el último punto de código es 0xxxxxxx o (10xxxxxx, 0xxxxxxx).

En realidad, hay esquemas de codificación más eficientes, donde ir al punto de código anterior se puede hacer en un tiempo constante, y los punteros a la mitad de un punto de código se pueden arreglar. Permitir los siguientes códigos:

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

Si uno de los tres bytes anteriores es ≥ 236, entonces es el comienzo de una secuencia de 3 bytes, porque no puede haber dos bytes de este tipo dentro de ninguna secuencia válida de 3 bytes. De lo contrario, si uno de los dos bytes anteriores es ≥ 128, entonces es el comienzo de una secuencia de dos bytes. De lo contrario, el byte anterior es un byte único < 128.

La búsqueda de una subcadena se vuelve un poco más difícil. Es posible que desee excluir cero bytes para que una cadena solo contenga un byte cero si contiene un punto de código cero.

    
respondido por el gnasher729 02.04.2017 - 00:38
-2

Respuesta corta, su propuesta de utf-8 es imposible de sincronizar. Una vez que tenga una secuencia dañada en su flujo de bytes, nunca podrá sincronizar realmente con la siguiente secuencia válida o con un solo byte. Esto se debe a que, efectivamente, tiene un byte de inicio, que comienza con 10 o 110, pero los bytes siguientes también pueden ser bytes de inicio y también bytes individuales.

La forma en que se ha diseñado el utf-8, siempre puede detectar un solo byte, un byte de inicio y un byte siguiente.

    
respondido por el brighty 28.04.2015 - 12:59

Lea otras preguntas en las etiquetas