¿Es UTF-16 de ancho fijo o variable? ¿Por qué UTF-8 no tiene problemas de orden de bytes?

15
  1. ¿Es UTF-16 de ancho fijo o de ancho variable? Tengo diferentes resultados de diferentes fuentes:

    De enlace :

      

    UTF-16 almacena caracteres Unicode en fragmentos de dieciséis bits.

    De enlace :

      

    UTF-16 (Formato de transformación Unicode de 16 bits) es un carácter   codificación   para Unicode capaz de codificar números 1,112,064 [1] (llamado código   puntos) en el espacio de código Unicode de 0 a 0x10FFFF. Produce   una   resultado de longitud variable de una o dos unidades de código de 16 bits por   código   punto.

  2. Desde la primera fuente

      

    UTF-8 también tiene la ventaja de que la unidad de codificación es la   byte, entonces   no hay problemas de ordenación de bytes.

    ¿Por qué UTF-8 no tiene problemas de orden de bytes? Es de ancho variable, y un carácter puede contener más de un byte, por lo que creo que el orden de bytes ¿Todavía puede ser un problema?

Gracias y saludos!

    
pregunta Tim 23.07.2011 - 01:45
fuente

2 respuestas

12
  

(1) ¿Qué significa la secuencia de bytes, un arrary de char en C? ¿Es UTF-16 una secuencia de bytes, o qué es entonces? (2) ¿Por qué una secuencia de bytes no tiene nada que ver con la longitud variable?

Parece que estás malinterpretando qué son los problemas endianos. Aquí hay un breve resumen.

Un entero de 32 bits ocupa 4 bytes. Ahora, sabemos el orden lógico de estos bytes. Si tiene un entero de 32 bits, puede obtener el byte superior de este con el siguiente código:

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

Eso está muy bien. Donde comienza el problema es cómo varias ferreterías recuperan enteros de la memoria.

En el orden de Big Endian, se leerá un fragmento de memoria de 4 bytes que lea como un entero de 32 bits, siendo el primer byte el byte alto:

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

En el orden de Little Endian, se leerá un fragmento de memoria de 4 bytes que lea como un entero de 32 bits, siendo el primer byte el byte bajo :

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

Si tiene un puntero a un puntero a un valor de 32 bits, puede hacer esto:

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

De acuerdo con C / C ++, el resultado de esto es indefinido. Podría ser 0x81. O podría ser 0x32. Técnicamente, podría devolver cualquier cosa, pero para sistemas reales, devolverá uno u otro.

Si tiene un puntero a una dirección de memoria, puede leer esa dirección como un valor de 32 bits, un valor de 16 bits o un valor de 8 bits. En una máquina big endian, el puntero apunta al byte alto; en una pequeña máquina endiana, el puntero apunta al byte bajo.

Tenga en cuenta que se trata de leer y escribir en la memoria. No tiene nada que ver con el código interno de C / C ++. La primera versión del código, la que C / C ++ no declara como no definida, siempre funcionará para obtener el byte alto.

El problema es cuando empiezas a leer flujos de bytes. Por ejemplo, de un archivo.

Los valores de 16 bits tienen los mismos problemas que los de 32 bits; solo tienen 2 bytes en lugar de 4. Por lo tanto, un archivo podría contener valores de 16 bits almacenados en orden big endian o little endian.

UTF-16 se define como una secuencia de valores de 16 bits . Efectivamente, es un uint16_t[] . Cada unidad de código individual es un valor de 16 bits. Por lo tanto, para cargar UTF-16 correctamente, debe saber cuál es la naturaleza de los datos.

UTF-8 se define como una secuencia de valores de 8 bits . Es un uint8_t[] . Cada unidad de código individual tiene un tamaño de 8 bits: un solo byte.

Ahora, tanto UTF-16 como UTF-8 permiten que múltiples unidades de código (valores de 16 bits u 8 bits) se combinen para formar un punto de código Unicode (un "carácter", pero eso es no el término correcto; es una simplificación). El orden de estas unidades de código que forman un punto de código está dictado por las codificaciones UTF-16 y UTF-8.

Al procesar UTF-16, lee un valor de 16 bits, haciendo lo que sea necesario para la conversión endian. Entonces, se detecta si es un par sustituto; si es así, entonces lees otro valor de 16 bits, combinas los dos, y de ese modo obtienes el valor de punto de código Unicode.

Al procesar UTF-8, lees un valor de 8 bits. Ninguna conversión endiana es posible, ya que solo hay un byte. Si el primer byte denota una secuencia de múltiples bytes, entonces lee un número de bytes, según lo dictado por la secuencia de múltiples bytes. Cada byte individual es un byte y, por lo tanto, no tiene conversión endiana. El orden de estos bytes en la secuencia, al igual que el orden de los pares sustitutos en UTF-16, está definido por UTF-8.

Por lo tanto, no puede haber problemas de endian con UTF-8.

    
respondido por el Nicol Bolas 24.07.2011 - 02:00
fuente
10

La respuesta de Jeremy Banks es correcta hasta el momento, pero no abordó la ordenación de bytes.

Cuando usas UTF-16, la mayoría de los glifos se almacenan usando una palabra de dos bytes, pero cuando la palabra se almacena en un archivo de disco, ¿qué orden usas para almacenar los bytes constituyentes?

Como ejemplo, el glifo CJK (chino) para la palabra "agua" tiene una codificación UTF-16 en hexadecimal de 6C34. Cuando escribe eso como dos bytes en el disco, ¿lo escribe como "big-endian" (los dos bytes son 6C 34)? ¿O lo escribe como "little-endian (los dos bytes son 34 6C)?

Con UTF-16, ambos ordenamientos son legítimos, y generalmente indica cuál tiene el archivo al hacer que la primera palabra en el archivo sea una marca de orden de bytes (BOM), que para la codificación de big-endian es FE FF, y La codificación little-endian es FF FE.

UTF-32 tiene el mismo problema y la misma solución.

UTF-8 no tiene este problema, porque es de longitud variable, y usted escribe efectivamente la secuencia de bytes de un glifo como si fuera little-endian. Por ejemplo, la letra "P" siempre se codifica con un byte (80) y el carácter de reemplazo siempre se codifica con los dos bytes FF FD en ese orden.

Algunos programas ponen un indicador de tres bytes (EF BB BF) al inicio de un archivo UTF-8, y eso ayuda a distinguir UTF-8 de codificaciones similares como ASCII, pero eso no es muy común, excepto en MS Windows.

    
respondido por el Bob Murphy 23.07.2011 - 02:29
fuente

Lea otras preguntas en las etiquetas