UTF-16
UTF-16 (formato de transformación Unicode de 16 bits) es una codificación de caracteres capaz de codificar los 1 112 064 puntos de código válidos de Unicode (de hecho, este número de puntos de código está dictado por el diseño de UTF -dieciséis). La codificación es de longitud variable, ya que los puntos de código se codifican con una o dos unidades de código de 16 bits. UTF-16 surgió de una codificación obsoleta anterior de 16 bits de ancho fijo, ahora conocida como UCS-2 (para conjunto de caracteres universales de 2 bytes), una vez que quedó claro que más de 216 (65 536) se necesitaban puntos de código.
UTF-16 es utilizado por sistemas como la API de Microsoft Windows, el lenguaje de programación Java y JavaScript/ECMAScript. A veces también se usa para archivos de datos de procesamiento de textos y texto sin formato en Microsoft Windows. Rara vez se usa para archivos en sistemas similares a Unix.
Con frecuencia, se afirma que UTF-16 es más eficiente en cuanto al espacio que UTF-8 para los idiomas de Asia oriental, ya que utiliza dos bytes para los caracteres que ocupan 3 bytes en UTF-8. Dado que el texto real contiene muchos espacios, números, puntuación, marcado y caracteres de control, que ocupan solo un byte en UTF-8, esto solo es cierto para bloques de texto densos construidos artificialmente. Además, GB 18030 (que también es compatible con Unicode) siempre es más corto que UTF-16.
UTF-16 es la única codificación web incompatible con ASCII y nunca ganó popularidad en la web, donde se declara en menos del 0,002 % (poco más de 1 milésima parte del 1 por ciento) de las páginas web, e incluso entonces UTF-8 se usa a menudo, aunque UTF-16 (también) se especifica (es decir, debido a "especificaciones de codificación de caracteres contradictorias" y/o "codificación de caracteres incorrecta definida"). UTF-8, en comparación, representa el 98% de todas las páginas web. El Grupo de Trabajo de Tecnología de Aplicaciones de Hipertexto Web (WHATWG) considera que UTF-8 "la codificación obligatoria para todos los [textos]" y que, por razones de seguridad, las aplicaciones del navegador no deben usar UTF-16.
Es utilizado por SMS (es decir, el UTF-16 de longitud variable necesario para admitir todos los caracteres emoji, el estándar de SMS especifica su predecesor UCS-2 de ancho fijo que no admite la mayoría de ellos).
Historia
A fines de la década de 1980, se comenzó a trabajar en el desarrollo de una codificación uniforme para un "Conjunto de caracteres universal" (UCS) que reemplazaría las codificaciones anteriores específicas del idioma con un sistema coordinado. El objetivo era incluir todos los caracteres necesarios de la mayoría de los idiomas del mundo, así como símbolos de dominios técnicos como la ciencia, las matemáticas y la música. La idea original era reemplazar las codificaciones típicas de 256 caracteres, que requerían 1 byte por carácter, con una codificación que usaba 65 536 (216) valores, lo que requeriría 2 bytes (16 bits) por carácter.
Dos grupos trabajaron en esto en paralelo, ISO/IEC JTC 1/SC 2 y el Consorcio Unicode, este último que representa principalmente a fabricantes de equipos informáticos. Los dos grupos intentaron sincronizar sus asignaciones de caracteres para que las codificaciones en desarrollo fueran mutuamente compatibles. La primera codificación de 2 bytes se llamaba originalmente "Unicode", pero ahora se llama "UCS-2".
Cuando se hizo cada vez más claro que 216 caracteres no serían suficientes, IEEE introdujo un espacio más grande de 31 bits y una codificación (UCS-4) que requeriría 4 bytes por carácter. El Consorcio Unicode se resistió a esto, tanto porque 4 bytes por carácter desperdiciaron mucha memoria y espacio en disco, como porque algunos fabricantes ya habían invertido mucho en la tecnología de 2 bytes por carácter. El esquema de codificación UTF-16 se desarrolló como compromiso y se introdujo con la versión 2.0 del estándar Unicode en julio de 1996. Está completamente especificado en RFC 2781, publicado en 2000 por el IETF.
En la codificación UTF-16, los puntos de código inferiores a 216 se codifican con una única unidad de código de 16 bits igual al valor numérico del punto de código, como en la antigua UCS-2. Los puntos de código más nuevos mayores o iguales a 216 están codificados por un valor compuesto utilizando dos unidades de código de 16 bits. Estas dos unidades de código de 16 bits se eligen del rango suplente UTF-16 0xD800–0xDFFF que no se habían asignado previamente a caracteres. Los valores en este rango no se usan como caracteres y UTF-16 no proporciona una forma legal de codificarlos como puntos de código individuales. Por lo tanto, una secuencia UTF-16 consta de puntos de código de 16 bits únicos fuera del rango suplente para puntos de código en el plano multilingüe básico (BMP) y pares de valores de 16 bits dentro del rango suplente para puntos de código por encima del BMP.
UTF-16 se especifica en las últimas versiones tanto del estándar internacional ISO/IEC 10646 como del estándar Unicode. "UCS-2 ahora debe considerarse obsoleto. Ya no hace referencia a un formulario de codificación en 10646 o en el estándar Unicode." UTF-16 nunca se extenderá para admitir una mayor cantidad de puntos de código o para admitir los puntos de código que fueron reemplazados por sustitutos, ya que esto violaría la Política de estabilidad de Unicode con respecto a la categoría general o los puntos de código sustitutos. (Cualquier esquema que siga siendo un código de sincronización automática requerirá la asignación de al menos un punto de código BMP para iniciar una secuencia. No se permite cambiar el propósito de un punto de código).
Descripción
Cada punto de código Unicode se codifica como una o dos unidades de código de 16 bits. La forma en que estos códigos de 16 bits se almacenan como bytes depende de la endianidad del archivo de texto o del protocolo de comunicación.
Un "personaje" puede necesitar desde tan solo dos bytes hasta catorce o incluso más bytes para grabarse. Por ejemplo, un carácter de bandera emoji ocupa 8 bytes, ya que está "construido a partir de un par de valores escalares Unicode" (y esos valores están fuera del BMP y requieren 4 bytes cada uno).
U+0000 a U+D7FF y U+E000 a U+FFFF
Tanto UTF-16 como UCS-2 codifican puntos de código en este rango como unidades de código únicas de 16 bits que son numéricamente iguales a los puntos de código correspondientes. Estos puntos de código en el plano multilingüe básico (BMP) son los únicos puntos de código que se pueden representar en UCS-2. A partir de Unicode 9.0, algunas escrituras modernas no latinas de Asia, Medio Oriente y África quedan fuera de este rango, al igual que la mayoría de los caracteres emoji.
Puntos de código de U+010000 a U+10FFFF
Los puntos de código de los otros planos (llamados planos suplementarios) se codifican como dos unidades de código de 16 bits llamadas par suplente, mediante el siguiente esquema:
Baja Alto | DC00 | DC01 | ... | DFFF |
---|---|---|---|---|
D800 | 010000 | 010001 | ... | 0103FF |
D801 | 010400 | 010401 | ... | 0107FF |
⋮ | ⋮ | ⋮ | ⋱ | ⋮ |
DBFF | 10FC00 | 10FC01 | ... | 10FF |
- 0x10000 se resta del punto de código (U), dejando un número de 20 bits (U') en el rango de números hex 0x00000-0xFFF. Nota para estos fines, U se define como no más que 0x10FFFF.
- Los 10 bits altos (en el rango 0x000-0x3FF) se añaden a 0xD800 para dar el primer 16-bit unidad de código o Sustituto alto (W1), que estará en el rango 0xD800-0xDBFF.
- Los 10 bits bajos (también en el rango 0x000–0x3FF) se añaden a 0xDC00 para dar el segundo 16-bit unidad de código o Sustituto bajo (W2), que estará en el rango 0xDC00–0xDFFF.
Ilustrada visualmente, la distribución de U' entre W1 y W2 se parece a:
U' = yyyyyyyyyxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
W1 = 110110yyyyyyyyyyy // 0xD800 + yyyyyyyyyyyyyyyyyyyyy
W2 = 110111xxxxxxxxxxxxxx // 0xDC00 + xxxxxxxxxxxxxxx
El sustituto alto y el sustituto bajo también se conocen como "principales" y "trasero" sustitutos, respectivamente, análogos a los bytes iniciales y finales de UTF-8.
Dado que los rangos para los sustitutos altos (0xD800–0xDBFF), sustitutos bajos (0xDC00–0xDFFF), y los caracteres BMP válidos (0x0000–0xD7FF, 0xE000–0xFFFF) son disjuntos, no es posible que un sustituto coincida con un carácter BMP, o que dos unidades de código adyacentes para que parezcan un par sustituto legal. Esto simplifica mucho las búsquedas. También significa que UTF-16 se autosincroniza en palabras de 16 bits: se puede determinar si una unidad de código inicia un carácter sin examinar las unidades de código anteriores (es decir, el tipo de unidad de código se puede determinar por los rangos de valores en los que cae). UTF-8 comparte estas ventajas, pero muchos esquemas de codificación de varios bytes anteriores (como Shift JIS y otras codificaciones asiáticas de varios bytes) no permitían una búsqueda inequívoca y solo podían sincronizarse volviendo a analizar desde el principio de la cadena. UTF-16 no se sincroniza automáticamente si se pierde un byte o si el recorrido comienza en un byte aleatorio.
Debido a que los caracteres que se usan con más frecuencia están todos en el BMP, el manejo de pares sustitutos a menudo no se prueba a fondo. Esto conduce a errores persistentes y posibles agujeros de seguridad, incluso en aplicaciones de software populares y bien revisadas (p. ej., CVE-2008-2938, CVE-2012-2135).
Los Planos Suplementarios contienen emojis, guiones históricos, símbolos menos usados, ideogramas chinos menos usados, etc. Dado que la codificación de los Planos Suplementarios contiene 20 bits significativos (10 de 16 bits en cada uno de los altos y sustitutos bajos), se pueden codificar 220 puntos de código, divididos en 16 planos de 216 puntos de código cada uno. Incluyendo el Plano Básico Multilingüe manejado por separado, hay un total de 17 aviones.
U+D800 a U+DFFF
El estándar Unicode reserva estos valores de punto de código para los sustitutos alto y bajo, y nunca se les asignará un carácter, por lo que no debería haber ninguna razón para codificarlos. El estándar oficial de Unicode dice que ningún formulario UTF, incluido UTF-16, puede codificar estos puntos de código. Sin embargo, Windows permite sustitutos no emparejados en nombres de archivo y otros lugares, lo que generalmente significa que deben ser compatibles con software a pesar de su exclusión del estándar Unicode.
UCS-2, UTF-8 y UTF-32 pueden codificar estos puntos de código de maneras triviales y obvias, y una gran cantidad de software lo hace, aunque el estándar establece que tales arreglos deben tratarse como errores de codificación.
Es posible codificar sin ambigüedades un suplente no emparejado (un punto de código sustituto alto no seguido por uno bajo, o uno bajo no precedido por uno alto) en formato UTF-16 utilizando una unidad de código igual al punto de código. El resultado no es UTF-16 válido, pero la mayoría de las implementaciones de codificadores y decodificadores UTF-16 hacen esto cuando se traducen entre codificaciones.
Ejemplos
Para codificar U+10437 (𐐷) a UTF-16:
- Extracto 0x10000 del punto de código, dejando 0x0437.
- Para el surrogado alto, cambie a la derecha por 10 (divide por 0x400), a continuación, añadir 0xD800, resultando en 0x0001 + 0xD800 = 0xD801.
- Para el surrogado bajo, tome los 10 bits bajos (remanente de división por 0x400), a continuación, añadir 0xDC00, resultando en 0x0037 + 0xDC00 = 0xDC37.
Para decodificar U+10437 (𐐷) de UTF-16:
- Tome el surrogado alto (0xD801) y restar 0xD800, luego se multiplica por 0x400, dando como resultado 0x0001 × 0x400 = 0x0400.
- Tome el surrogado bajo (0xDC37) y restar 0xDC00, lo que resulta en 0x37.
- Añadir estos dos resultados juntos (0x0437), y finalmente añadir 0x10000 para obtener el punto final decodificado UTF-32, 0x10437.
La siguiente tabla resume esta conversión, así como otras. Los colores indican cómo se distribuyen los bits del punto de código entre los bytes UTF-16. Los bits adicionales agregados por el proceso de codificación UTF-16 se muestran en negro.
Cara | Punto de código binario | Binary UTF-16 | UTF-16 hex unidades de código | UTF-16BE Hex bytes | UTF-16LE Hex bytes | |
---|---|---|---|---|---|---|
$ | U+0024 | 0000 0000 0010 0100 | 0000 0000 0010 0100 | 0024 | 00 24 | 24 00 |
€ | U+20AC | 0010 0000 1010 1100 | 0010 0000 1010 1100 | 20AC | 20 AC | AC 20 |
𐐷 | U+10437 | 0001 0000 0100 0011 0111 | 1101 1000 0000 0001 1101 1100 0011 0111 | D801 DC37 | D8 01 DC 37 | 01 D8 37 DC |
𤭢 | U+24B62 | 0010 0100 1011 0110 0010 | 1101 1000 0101 0010 1101 1111 0110 0010 | D852 DF62 | D8 52 DF 62 | 52 D8 62 DF |
Esquemas de codificación por orden de bytes
UTF-16 y UCS-2 producen una secuencia de unidades de código de 16 bits. Dado que la mayoría de los protocolos de comunicación y almacenamiento están definidos por bytes, y cada unidad toma dos bytes de 8 bits, el orden de los bytes puede depender del endianness (orden de bytes) de la arquitectura de la computadora.
Para ayudar a reconocer el orden de bytes de las unidades de código, UTF-16 permite que una marca de orden de bytes (BOM), un punto de código con el valor U+FEFF, preceda al primer valor codificado real.. (U+FEFF es el carácter ZWNBSP/espacio invisible de ancho cero que no se rompe). Si la arquitectura endian del decodificador coincide con la del codificador, el decodificador detecta el valor 0xFEFF, pero un decodificador endian opuesto interpreta la lista de materiales como la valor no caracter U+FFFE reservado para este propósito. Este resultado incorrecto proporciona una sugerencia para realizar un intercambio de bytes para los valores restantes.
Si falta la lista de materiales, RFC 2781 recomienda asumir la codificación big-endian (BE). En la práctica, debido a que Windows usa el orden little-endian (LE) de manera predeterminada, muchas aplicaciones asumen la codificación little-endian. También es fiable detectar endianness buscando bytes nulos, suponiendo que los caracteres inferiores a U+0100 son muy comunes. Si más bytes pares (a partir de 0) son nulos, entonces es big-endian.
El estándar también permite que el orden de los bytes se indique explícitamente especificando UTF-16BE o UTF-16LE como tipo de codificación. Cuando el orden de los bytes se especifica explícitamente de esta manera, se supone específicamente que una BOM no debe anteponerse al texto, y un U+FEFF al principio debe manejarse como un carácter ZWNBSP. La mayoría de las aplicaciones ignoran una lista de materiales en todos los casos a pesar de esta regla.
Para los protocolos de Internet, la IANA ha aprobado "UTF-16", "UTF-16BE" y "UTF-16LE" como los nombres de estas codificaciones (los nombres no distinguen entre mayúsculas y minúsculas). Los alias UTF_16 o UTF16 pueden tener significado en algunos lenguajes de programación o aplicaciones de software, pero no son nombres estándar en los protocolos de Internet.
Se utilizan designaciones similares, UCS-2BE y UCS-2LE, para mostrar versiones de UCS-2.
Uso
UTF-16 se usa para texto en la API del sistema operativo de todas las versiones actualmente admitidas de Microsoft Windows (e incluidas al menos todas desde Windows CE/2000/XP/2003/Vista/7), incluido Windows 10. En Windows XP, no se incluye ningún punto de código por encima de U+FFFF en ninguna fuente entregada con Windows para idiomas europeos. Los sistemas Windows NT más antiguos (anteriores a Windows 2000) solo admiten UCS-2. Los archivos y los datos de red tienden a ser una combinación de codificaciones de bytes heredadas, UTF-16 y UTF-8.
Si bien ha habido algo de compatibilidad con UTF-8 incluso para Windows XP, se mejoró (en particular, la capacidad de nombrar un archivo usando UTF-8) en Windows 10 Insider build 17035 y la actualización de mayo de 2019. A partir de mayo de 2019, Microsoft recomienda que el software use UTF-8 en lugar de otras codificaciones de 8 bits. No está claro si recomiendan el uso de UTF-8 sobre UTF-16.
El sistema operativo IBM i designa el CCSID (página de códigos) 13488 para la codificación UCS-2 y el CCSID 1200 para la codificación UTF-16, aunque el sistema los trata a ambos como UTF-16.
UTF-16 es utilizado por los sistemas operativos Qualcomm BREW; los entornos.NET; y el kit de herramientas de widgets gráficos multiplataforma de Qt.
El sistema operativo Symbian utilizado en los teléfonos Nokia S60 y los teléfonos Sony Ericsson UIQ utilizan UCS-2. Los teléfonos iPhone usan UTF-16 para el servicio de mensajes cortos en lugar de UCS-2 descrito en los estándares 3GPP TS 23.038 (GSM) e IS-637 (CDMA).
El sistema de archivos Joliet, utilizado en soportes de CD-ROM, codifica los nombres de los archivos mediante UCS-2BE (hasta sesenta y cuatro caracteres Unicode por nombre de archivo).
El entorno del lenguaje Python oficialmente solo usó UCS-2 internamente desde la versión 2.0, pero el decodificador UTF-8 para "Unicode" produce UTF-16 correcto. Desde Python 2.2, "ancho" Se admiten compilaciones de Unicode que usan UTF-32 en su lugar; estos se utilizan principalmente en Linux. Python 3.3 ya no usa UTF-16, en su lugar, se elige una codificación que brinda la representación más compacta para la cadena dada de ASCII/Latin-1, UCS-2 y UTF-32.
Java usó originalmente UCS-2 y agregó soporte de caracteres complementarios UTF-16 en J2SE 5.0.
JavaScript puede usar UCS-2 o UTF-16. A partir de ES2015, se agregaron al lenguaje métodos de cadenas y marcas de expresiones regulares que permiten manejar cadenas desde una perspectiva independiente de la codificación.
En muchos idiomas, las cadenas entrecomilladas necesitan una nueva sintaxis para citar caracteres que no son BMP, ya que la sintaxis "uXXXX"
de estilo C se limita explícitamente a 4 dígitos hexadecimales. Los siguientes ejemplos ilustran la sintaxis del carácter no BMP "𝄞" (U+1D11E, CLAVE DE G DEL SÍMBOLO MUSICAL):
- El más común (utilizado por C++, C#, D y varios otros idiomas) es utilizar un 'U' mayúscula con 8 dígitos de hex como
"U0001D11E"
. - En Java 7 expresiones regulares, UCI y Perl, la sintaxis
"x{1D11E}"
debe ser utilizado; de forma similar, en ECMAScript 2015 (JavaScript), el formato de escape es"u{1D11E}"
. - En muchos otros casos (como Java fuera de las expresiones regulares), la única manera de conseguir caracteres no BMP es entrar a las mitades sustitutas individualmente, por ejemplo:
"uD834uDD1E"
para U+1D11E.
Las implementaciones de cadenas basadas en UTF-16 suelen definir las longitudes de la cadena y permiten la indexación en términos de estas unidades de código de 16 bits, no en términos de puntos de código. Ni los puntos de código ni las unidades de código corresponden a nada que un usuario final pueda reconocer como un "carácter"; las cosas que los usuarios identifican como caracteres pueden, en general, consistir en un punto de código base y una secuencia de combinación de caracteres (o podría ser una secuencia de puntos de código de algún otro tipo, por ejemplo, Hangul uniendo jamos): Unicode se refiere a esta construcción como clúster de grafemas – y, como tal, las aplicaciones que manejan cadenas Unicode, independientemente de la codificación, deben lidiar con el hecho de que esto limita su capacidad para dividir y combinar cadenas arbitrariamente.
UCS-2 también es compatible con el lenguaje PHP y MySQL.
Swift, versión 5, el lenguaje de aplicación preferido de Apple, cambió de UTF-16 a UTF-8 como la codificación preferida.
Si bien UTF-16 ocupa la mitad de espacio que UTF-8 para ASCII, es más eficiente para (algunos caracteres de) los idiomas de Asia oriental, el estándar de codificación chino Unicode GB 18030 siempre produce archivos del mismo tamaño o más pequeños que UTF-16 (o UTF-8) para todos los idiomas, no solo para chino. Además, los archivos ASCII se pueden decodificar (son un subconjunto de GB 18030), es decir, los caracteres ASCII se codifican con 1 byte por letra, a diferencia de UTF-16. Se necesitan 2 bytes por letra, p. Devanagari y bengalí, mientras que en UTF-8 ocupan 3 bytes.
Contenido relacionado
Verificación de redundancia cíclica
Host
Codigo hamming