Este artículo compara las codificaciones Unicode en dos tipos de entornos: entornos limpios de 8 bits y entornos que prohíben el uso de valores de bytes con el bit alto establecido. Originalmente, dichas prohibiciones permitían enlaces que utilizaban solo siete bits de datos, pero siguen existiendo en algunos estándares y, por lo tanto, algunos programas que cumplen con los estándares deben generar mensajes que cumplan con las restricciones. [ Se necesita más explicación ] El esquema de compresión estándar para Unicode y la compresión binaria ordenada para Unicode se excluyen de las tablas de comparación porque es difícil cuantificar simplemente su tamaño.
Un archivo UTF-8 que contiene solo caracteres ASCII es idéntico a un archivo ASCII. Los programas antiguos generalmente pueden manejar archivos codificados en UTF-8, incluso si contienen caracteres que no son ASCII. Por ejemplo, la función printf de C puede imprimir una cadena UTF-8 porque solo busca el carácter ASCII '%' para definir una cadena de formato. Todos los demás bytes se imprimen sin cambios.
UTF-16 y UTF-32 son incompatibles con los archivos ASCII y, por lo tanto, requieren programas compatibles con Unicode para mostrarlos, imprimirlos y manipularlos incluso si se sabe que el archivo contiene solo caracteres del subconjunto ASCII. Debido a que contienen muchos bytes cero, las cadenas de caracteres que representan dichos archivos no pueden manipularse mediante la lógica común de manejo de cadenas terminadas en nulo . [a] La prevalencia del manejo de cadenas utilizando esta lógica significa que, incluso en el contexto de sistemas UTF-16 como Windows y Java , los archivos de texto UTF-16 no se usan comúnmente. En cambio, aún se usan codificaciones de 8 bits más antiguas como ASCII o ISO-8859-1 , renunciando por completo al soporte Unicode, o se usa UTF-8 para Unicode. [ cita requerida ] Un contraejemplo poco común es el archivo "strings" introducido en Mac OS X 10.3 Panther , que es utilizado por aplicaciones para buscar versiones internacionalizadas de mensajes. De forma predeterminada, este archivo está codificado en UTF-16 y "no se garantiza que los archivos codificados con UTF-8 funcionen". [1]
XML se codifica convencionalmente como UTF-8, [ cita requerida ] y todos los procesadores XML deben soportar al menos UTF-8 y UTF-16. [2]
UTF-8 requiere 8, 16, 24 o 32 bits (de uno a cuatro bytes ) para codificar un carácter Unicode, UTF-16 requiere 16 o 32 bits para codificar un carácter y UTF-32 siempre requiere 32 bits para codificar un carácter.
Los primeros 128 puntos de código Unicode , U+0000 a U+007F, que se utilizan para los controles C0 y los caracteres latinos básicos y que corresponden a ASCII, se codifican utilizando 8 bits en UTF-8, 16 bits en UTF-16 y 32 bits en UTF-32. Los siguientes 1.920 caracteres, U+0080 a U+07FF, representan el resto de los caracteres utilizados por casi todos los alfabetos de escritura latina , así como el griego , cirílico , copto , armenio , hebreo , árabe , siríaco , thaana y n'ko . Los caracteres de este rango requieren 16 bits para codificarse tanto en UTF-8 como en UTF-16, y 32 bits en UTF-32. Para U+0800 a U+FFFF, los caracteres restantes del Plano Multilingüe Básico y capaces de representar el resto de caracteres de la mayoría de los idiomas vivos del mundo, UTF-8 necesita 24 bits para codificar un carácter mientras que UTF-16 necesita 16 bits y UTF-32 necesita 32. Los puntos de código U+010000 a U+10FFFF, que representan caracteres en los planos suplementarios , requieren 32 bits en UTF-8, UTF-16 y UTF-32.
Un archivo es más corto en UTF-8 que en UTF-16 si hay más puntos de código ASCII que puntos de código en el rango U+0800 a U+FFFF. Los defensores de UTF-8 como la forma preferida argumentan que los documentos del mundo real escritos en idiomas que usan caracteres solo en el rango alto a menudo siguen siendo más cortos en UTF-8 debido al uso extensivo de espacios, dígitos, puntuación, nuevas líneas, HTML y palabras incrustadas y acrónimos escritos con letras latinas. [3] UTF-32, por el contrario, siempre es más largo a menos que no haya puntos de código menores que U+10000.
Todos los caracteres imprimibles en UTF-EBCDIC utilizan al menos tantos bytes como en UTF-8, y la mayoría utiliza más, debido a una decisión tomada para permitir la codificación de los códigos de control C1 como bytes individuales. Para entornos de siete bits, UTF-7 es más eficiente en términos de espacio que la combinación de otras codificaciones Unicode con quoted-printable o base64 para casi todos los tipos de texto [ se necesita más explicación ] (consulte "Entornos de siete bits" a continuación).
El texto con codificación de longitud variable, como UTF-8 o UTF-16, es más difícil de procesar si es necesario trabajar con unidades de código individuales en lugar de hacerlo con puntos de código. La búsqueda no se ve afectada por el tamaño variable de los caracteres, ya que una búsqueda de una secuencia de unidades de código no tiene en cuenta las divisiones. Sin embargo, sí requiere que la codificación se sincronice automáticamente , lo que es el caso tanto de UTF-8 como de UTF-16. Un error común es creer que es necesario "encontrar el n -ésimo carácter" y que esto requiere una codificación de longitud fija; sin embargo, en el uso real, el número n solo se deriva del examen de los n−1 caracteres, por lo que, de todos modos, se necesita acceso secuencial. [ cita requerida ]
El uso eficiente de secuencias de caracteres en un orden endian cargado en una máquina con un orden endian diferente requiere procesamiento adicional. Los caracteres pueden convertirse antes de su uso o procesarse con dos sistemas distintos. Las codificaciones basadas en bytes como UTF-8 no tienen este problema. [ ¿Por qué? ] UTF-16BE y UTF-32BE son big-endian , UTF-16LE y UTF-32LE son little-endian .
Para su procesamiento, un formato debe ser fácil de buscar, truncar y, en general, procesar de forma segura. [ cita requerida ] Todas las codificaciones Unicode normales utilizan algún tipo de unidad de código de tamaño fijo. Según el formato y el punto de código que se va a codificar, una o más de estas unidades de código representarán un punto de código Unicode . Para permitir una búsqueda y un truncamiento sencillos, una secuencia no debe aparecer dentro de una secuencia más larga o en el límite de otras dos secuencias. UTF-8, UTF-16, UTF-32 y UTF-EBCDIC tienen estas importantes propiedades, pero UTF-7 y GB 18030 no.
Los caracteres de tamaño fijo pueden ser útiles, pero incluso si hay un recuento fijo de bytes por punto de código (como en UTF-32), no hay un recuento fijo de bytes por carácter mostrado debido a la combinación de caracteres . Teniendo en cuenta estas incompatibilidades y otras peculiaridades entre los diferentes esquemas de codificación, el manejo de datos Unicode con el mismo protocolo (o compatible) en todas las interfaces (por ejemplo, utilizando una API/biblioteca, manejando caracteres Unicode en el modelo cliente/servidor, etc.) puede, en general, simplificar todo el proceso y, al mismo tiempo, eliminar una fuente potencial de errores.
UTF-16 es popular porque muchas API datan de la época en que Unicode tenía un ancho fijo de 16 bits (conocido como UCS-2). Sin embargo, el uso de UTF-16 convierte a los caracteres fuera del plano multilingüe básico en un caso especial, lo que aumenta el riesgo de descuidos relacionados con su manejo. Dicho esto, los programas que manejan mal los pares sustitutos probablemente también tengan problemas con la combinación de secuencias, por lo que es poco probable que el uso de UTF-32 resuelva el problema más general del manejo deficiente de caracteres con múltiples unidades de código.
Si algún dato almacenado está en UTF-8 (como el contenido o los nombres de los archivos), es muy difícil escribir un sistema que utilice UTF-16 o UTF-32 como API. Esto se debe al hecho, que a menudo se pasa por alto, de que la matriz de bytes que utiliza UTF-8 puede contener físicamente secuencias no válidas. Por ejemplo, es imposible corregir un nombre de archivo UTF-8 no válido utilizando una API UTF-16, ya que ninguna cadena UTF-16 posible se traducirá a ese nombre de archivo no válido. Lo contrario no es cierto: es trivial traducir UTF-16 no válido a una cadena UTF-8 única (aunque técnicamente no válida), por lo que una API UTF-8 puede controlar archivos y nombres tanto UTF-8 como UTF-16, lo que hace que UTF-8 sea el preferido en cualquier entorno mixto de este tipo. Una solución alternativa desafortunada pero mucho más común utilizada por los sistemas UTF-16 es interpretar el UTF-8 como alguna otra codificación como CP-1252 e ignorar el mojibake para cualquier dato que no sea ASCII.
Los formatos UTF-16 y UTF-32 no tienen un orden de bytes definido, por lo que se debe seleccionar un orden de bytes al recibirlos a través de una red orientada a bytes o leerlos desde un almacenamiento orientado a bytes. Esto se puede lograr utilizando una marca de orden de bytes al comienzo del texto o asumiendo un orden de bytes grande (RFC 2781). UTF-8 , UTF-16BE , UTF-32BE , UTF-16LE y UTF-32LE están estandarizados en un solo orden de bytes y no tienen este problema.
Si el flujo de bytes está sujeto a corrupción , algunas codificaciones se recuperan mejor que otras. UTF-8 y UTF-EBCDIC son mejores en este sentido, ya que siempre pueden resincronizarse después de un byte corrupto o faltante al comienzo del siguiente punto de código; GB 18030 no puede recuperarse hasta el siguiente número ASCII no numérico. UTF-16 puede manejar bytes alterados , pero no un número impar de bytes faltantes , que distorsionarán todo el texto siguiente (aunque producirán caracteres poco comunes y/o no asignados). [b] Si se pueden perder bits , todos ellos distorsionarán el texto siguiente, aunque UTF-8 se puede resincronizar ya que los límites de bytes incorrectos producirán UTF-8 no válido en casi todos los textos de más de unos pocos bytes.
Las tablas siguientes enumeran la cantidad de bytes por punto de código para diferentes rangos Unicode. En la tabla se incluyen todos los comentarios adicionales necesarios. Las cifras suponen que los gastos generales al principio y al final del bloque de texto son insignificantes.
Nota: las tablas siguientes enumeran la cantidad de bytes por punto de código , no por "carácter" visible para el usuario (o "grupo de grafemas"). Pueden necesitarse varios puntos de código para describir un único grupo de grafemas, por lo que incluso en UTF-32 se debe tener cuidado al dividir o concatenar cadenas.
Es posible que esta tabla no cubra todos los casos especiales, por lo que debe utilizarse únicamente con fines de estimación y comparación. Para determinar con precisión el tamaño del texto en una codificación, consulte las especificaciones reales.
El orden de bytes no afecta los tamaños ( UTF-16BE y UTF-32BE tienen el mismo tamaño que UTF-16LE y UTF-32LE , respectivamente). El uso de UTF-32 en quoted-printable es muy poco práctico, pero si se implementa, dará como resultado 8-12 bytes por punto de código (aproximadamente 10 bytes en promedio), es decir, para BMP, cada punto de código ocupará exactamente 6 bytes más que el mismo código en quoted-printable/UTF-16. Base64/UTF-32 obtiene 5+1 ⁄ 3 bytes para cualquier punto de código.
Un carácter de control ASCII en formato quoted-printable o UTF-7 puede representarse directamente o codificarse (con caracteres de escape). La necesidad de utilizar caracteres de escape para un carácter de control determinado depende de muchas circunstancias, pero las nuevas líneas en los datos de texto suelen codificarse directamente.
BOCU-1 y SCSU son dos formas de comprimir datos Unicode. Su codificación depende de la frecuencia con la que se utiliza el texto. La mayoría de las secuencias de texto utilizan el mismo alfabeto; por ejemplo, latino , cirílico , griego , etc. Este uso normal permite que muchas secuencias de texto se compriman hasta aproximadamente 1 byte por punto de código. Estas codificaciones con estado hacen que sea más difícil acceder aleatoriamente al texto en cualquier posición de una cadena.
Estos dos esquemas de compresión no son tan eficientes como otros esquemas de compresión, como zip o bzip2 . Estos esquemas de compresión de propósito general pueden comprimir secuencias más largas de bytes a solo unos pocos bytes. Los esquemas de compresión SCSU y BOCU-1 no comprimirán más del 25 % teórico del texto codificado como UTF-8, UTF-16 o UTF-32. Otros esquemas de compresión de propósito general pueden comprimir fácilmente hasta el 10 % del tamaño del texto original. Los esquemas de propósito general requieren algoritmos más complicados y fragmentos de texto más largos para una buena relación de compresión.
La nota técnica Unicode n.° 14 contiene una comparación más detallada de los esquemas de compresión.
Se han hecho propuestas para la internacionalización de los nombres de dominio (IDN) en UTF-5 y UTF-6. La propuesta UTF-5 utilizaba una codificación de base 32 , mientras que Punycode es (entre otras cosas, y no exactamente) una codificación de base 36. El nombre UTF-5 para una unidad de código de 5 bits se explica mediante la ecuación 2 5 = 32. [4] La propuesta UTF-6 añadió una codificación de longitud continua a UTF-5, en la que 6 simplemente representa UTF-5 más 1. [ 5] El IETF IDN WG adoptó posteriormente el Punycode, más eficiente, para este propósito. [6]
El UTF-1 nunca fue aceptado seriamente. El UTF-8 se utiliza con mucha más frecuencia.
Las codificaciones nonetas UTF-9 y UTF-18 son especificaciones de broma del Día de los Inocentes de RFC , aunque UTF-9 es un formato de transformación Unicode nonetas funcional, y UTF-18 es una codificación nonetas funcional para todos los puntos de código que no sean de uso privado en Unicode 12 y anteriores, aunque no para áreas de uso privado suplementario o partes de Unicode 13 y posteriores .