Introducción a la codificación de caracteres

UTF-16

UTF-16 es un esquema de codificación de longitud variable de 16 bits y utiliza el conjunto de caracteres UTF para los puntos de código de caracteres. Esto significa que un carácter codificado UTF-16 tendrá una unidad de código de 16 bits.

Como sabemos que un carácter codificado UTF-8 se puede representar en 1 a 4 unidades de código, un carácter UTF-16 se puede representar en 1 o 2 unidades de código. Por lo tanto, un carácter UTF-16 puede tomar 16 o 32 bits de memoria en función de su punto de código.

Antes de entrar en las especificaciones de codificación UTF-16, entendamos cómo podemos hacer que funcione UTF-16.

Dado que tenemos una unidad de código de 16 bits, en teoría, podemos codificar 21 caracteres⁶ desde el punto de código 0 hasta 65.535. Pero, ¿qué pasa si tenemos un carácter con el punto de código mayor que 65.535? En ese caso, podemos agregar otra unidad de código.

Con la unidad de código adicional, podemos codificar un total de 232 caracteres, que es más de 4 m. Pero entonces la pregunta es, ¿cómo sabrá un decodificador UTF-16 que necesita considerar 2 unidades de código para decodificar un carácter?

UTF-8 resolvió este problema estableciendo bits iniciales de la primera unidad de código y unidades de código de continuación a algunos valores de bits específicos que un decodificador UTF-8 puede usar para deducir cuántas unidades de código puede tomar un personaje.

Podemos hacer lo mismo con la unidad de código UTF-16, pero luego tenemos que sacrificar algunos bits en una unidad de código para esta característica. Podemos establecer algunos bits iniciales de una unidad de código en algún valor significativo que un decodificador UTF-16 pueda entender.

También para dar potencia de auto-sincronización a las unidades de código, una unidad de código debe ser capaz de decir si es la unidad de código inicial o una unidad de código de continuación y no un carácter de una sola unidad de código.

Así que Unicode decidió sacrificar los 6 bits iniciales de la unidad de código dejando solo 10 bits para codificar el punto de código de un carácter por unidad de código. Si un carácter necesita 2 unidades de código, 20 bits de la memoria (de 32 bits o 4 bytes) contienen la información del punto de código real del carácter.

Entonces, ¿cuáles son estos bits iniciales y cómo estos bits hacen mella en el conjunto de caracteres UTF? Vamos a seguir el siguiente ejemplo.

1101 10xx xxxx xxxx 1101 11xx xxxx xxxx
FIRST CODE UNIT---- SECOND CODE UNIT---

Del estándar UTF-16, la primera unidad de código debe comenzar con 110110₂ y la segunda unidad de código debe comenzar con 110111₂. Esto ayudará a un decodificador UTF-16 a comprender cuál es la primera unidad de código y cuál es la segunda. Esto hace que el UTF-16 se sincronice automáticamente.

Ahora, con lo que tenemos 10 bits por unidad de código para jugar, ¿cuál es el rango dentro del que podemos jugar? Al final, ¿cuántos caracteres se pueden codificar en dos unidades de código de codificación UTF-16?

No se preocupe, hablaremos de caracteres codificados en una sola unidad de código.

Si echa un vistazo a las plantillas de unidades de código anteriores, tenemos un rango de 1101 1000 0000 0000₂ a 1101 1111 1111 1111₂. Eso es equivalente a d800 to a DFFF..

The La primera unidad de código tiene un rango de d800 to a 6fff.y la segunda unidad de código tiene un rango de dc00 to a dfff.. Podemos obtener estos valores activando y desactivando todos los bits de los puntos de código.

Dado que UTF-16 tiene que ser auto-sincronizado, los puntos de código entre d800₁₆ y dfff not no deben representar un carácter en UTF-16. Dado que todas las codificaciones UTF siguen el mismo conjunto de caracteres UTF, estos puntos de código están restringidos por UTF y no se asignan ni se asignarán a ningún carácter⁰.

Los puntos de código entre d800₁₆ y dfff not no representan ningún carácter, por lo que se denominan puntos de código sustitutos o juntos también se denominan pares sustitutos⁰.

El primer punto de código sustituto (de la primera unidad de código) también se llama alto sustituto y el segundo punto de código (de la segunda unidad de código) también se llama bajo sustituto. Haciendo el total de 2048 puntos de código, 1024 por madre sustituta.

points Los puntos de código sustitutos sacrificaban sus vidas para que pudiéramos codificar más caracteres con dos unidades de código. Pensar en eso!

Así que la gran pregunta, ¿podemos codificar un carácter con una sola unidad de código de UTF-16? La respuesta es SÍ. UTF-16 es un esquema de codificación de longitud variable de 16 bits. ¿Eso significa que podemos codificar 21 characters caracteres con una sola unidad de código?

La respuesta es NO. En teoría, podríamos codificar 21⁶ caracteres con código de punto de 0000₁₆ (0₁₀) a FFFF₁₆ (65535₁₀), pero los puntos de código entre D800₁₆ y DFFF₁₆ no representan ningún tipo de personajes como son reservados.

Por lo tanto, es seguro codificar caracteres de 0000 to a d7ff to y e000 to a ffff leaving dejando que cuentas a 63,488 (65536-2048) caracteres. Esto es solo para los caracteres que se pueden codificar en una sola unidad de código de UTF-16.

Dado que tenemos un total de 20 bits para jugar cuando se trata de caracteres que se pueden codificar en 2 unidades de código de UTF-16, podemos codificar 22 characters más caracteres, lo que es 1.048.576 caracteres.

En total, podemos codificar 1,048,576 + 63,488, lo que equivale a 1,112,064 caracteres (más de 1 millón de caracteres). Este es el límite del conjunto de caracteres UTF. Dado que UTF-16 puede codificar estos muchos caracteres, otras codificaciones UTF no pueden representar caracteres más allá de estos.

Puntos de código de conjunto de caracteres UTF

Como sabemos que un punto de código es un valor decimal asignado a un carácter, nosotros (Unicode) no debemos asignar un punto de código no válido a un carácter real. Hasta ahora, los puntos de código no válidos son puntos de código sustitutos.

Con una sola unidad de código UTF-16, podemos codificar 63.488 caracteres que van desde 0000 D a d7ff.y e000 to a ffff.. El último punto de código es 65.535. Estos se llaman caracteres BMP (explicados más adelante).

Con dos unidades de código UTF-16, podemos codificar 1.048.576 caracteres. Dado que no podemos comenzar de nuevo desde el valor 0 (punto de código) porque estos vienen después de los caracteres BMP, necesitamos compensarlos por 65,536. Estos caracteres se llaman caracteres suplementarios (explicados más adelante).

Por lo tanto, el primer carácter suplementario tiene un valor de punto de código de 65536 equivalent que es equivalente a 10000₁₆. Dado que podemos codificar 1.048.576 caracteres con dos unidades de código UTF-16, el último punto de código es 1114111 equivalent que es equivalente a 10ffff₁₆.

Así que vamos a desglosar las cosas en una forma tabular simple.

+-----------+---------------------+--------------------+
| UTF-16 CU | Code Point | |
+-----------+---------------------+--------------------+
| 1 | 0000₁₆ - D7FF₁₆ | valid |
+-----------+---------------------+--------------------+
| 1 | D800₁₆ - DFFF₁₆ | invalid(surrogate) |
+-----------+---------------------+--------------------+
| 1 | E000₁₆ - FFFF₁₆ | valid |
+-----------+---------------------+--------------------+
| 2 | 10000₁₆ - 10FFFF₁₆ | valid |
+-----------+---------------------+--------------------+
| | 110000₁₆ - FFFFFF₁₆ | unassigned |
+-----------+---------------------+--------------------+

Con este conocimiento, veamos cómo podemos codificar algunos caracteres en UTF-16. Vamos a elegir un carácter ASCII simple A (punto de código: 41₁₆), un carácter del idioma hindi (indio) आ (pronunciado como Aa, punto de código: 906.) y un emoticono Happy (llamado Cara feliz, punto de código: 1F60A.).

Como podemos ver en la tabla anterior, tanto A como आ se pueden codificar en una sola unidad de código de UTF-16, ya que sus valores son menores que ffff₁₆.

Cuando tenemos que codificar un carácter en una sola unidad de código, solo tenemos que convertir el punto de código del carácter en un número binario de 16 bits. Para los caracteres A, 00000000 01000001₂ es la representación UTF-16.

Del mismo modo, para el carácter आ, solo necesitamos convertir su punto de código 906₁₆ a un número binario de 16 bits que es 00001001 00000110₂.

Normalmente, representamos unidades de código de un carácter en números hexadecimales. Por lo tanto, para el carácter A, la representación UTF-16 es 0041 similarly y de manera similar, para el carácter, la representación UTF-16 is es 0906..

Para el personaje 😊, las cosas son un poco diferentes. Su punto de código es 1F60A₁₆. Si nos fijamos en la tabla UTF-16 mencionada anteriormente, tiene que estar codificada en 2 unidades de código de UTF-16. Entonces, ¿cómo empezamos?

Primero, necesitamos restar 10000₁₆ del punto de código. La razón es que cada carácter codificado en 2 unidades de código de UTF-16 viene después de los caracteres BMP cuyo último punto de código es FFFF₁₆.

Por lo tanto, para obtener el valor real de los bits utilizados para la codificación (que es 20 en 2 unidades de código), necesitamos restar 10000₁₆ del punto de código y usar el número final para generar estos 20 bits.

💡 Para ayudarlo a comprender mejor, el primer carácter representado con 2 unidades de código de UTF-16 tendrá todos sus 20 bits configurados en 0. Así que el valor de los bits utilizados para codificar el punto de código de este carácter es 0. Pero aún así, su punto de código es 10000 according de acuerdo con el conjunto de caracteres Unicode. Esto se debe a que el valor obtenido por estos 20 bits se agrega a 10000₁₆ para generar el punto de código final.

Como se ha visto anteriormente, estas 2 unidades de código se ven a continuación.

1101 10xx xxxx xxxx 1101 11xx xxxx xxxx
FIRST CODE UNIT---- SECOND CODE UNIT---

Solo necesitamos llenar estos 20 bits (x) con el valor recibido del punto de código de caracteres. El punto de código del carácter 😊es 1F60A₁₆. Pero primero, tenemos que restar 10000₁₆ de él. Tenemos F60A₁₆.

Ahora necesitamos convertir f60a₁₆ a un número binario de 20 bits y llenar los 20 bits en la plantilla de unidad de código anterior. f60a₁₆ en binario es 0000111101 1000001010₂. Ahora podemos llenar estos 20 bits de marcador de posición.

A continuación se muestran las unidades de código finales.

1101 1000 0011 1101 1101 1110 0000 1010
0xD83D 0xDE0A

La forma rápida de comprobar si estas unidades de código son válidas y, de hecho, si estos pares sustitutos pueden representar el carácter codificado, abra una herramienta de desarrollo del navegador e ingrese console.log('\uD83D\uDE0A'); en la consola.

(Herramientas para Desarrolladores de Chrome)

también puede utilizar esta herramienta online para generar código UTF-16 puntos.

Planos de caracteres Unicode

Un plano es un grupo continuo de 21 points o 65.536 puntos de código. Dado que UTF-16 ha restringido los puntos de código a un máximo de 10ffff₁₆, tenemos un total de planos de 17 caracteres en el estándar Unicode a partir de 0 a 16.

Dado que 21 caracteres⁶ se pueden definir por la unidad de código única de UTF-16 (incluidos los puntos de código sustitutos), forma el primer plano (0º). Este avión contiene casi todos los caracteres en idiomas básicos de todo el mundo. Esta es la razón por la que este plano se llama el Plano Multilingüe Básico o BMP.

A continuación, tenemos puntos de código definidos por dos unidades de código de UTF-16. Estos contienen 22 caracteres⁰ ya que tenemos 20 bits para codificar el valor del punto de código. Estos se dividen en 16 planos (2 x x 21.). Estos se llaman planos suplementarios.

read Para obtener más información sobre estos planos, lea este documento de Wikipedia.

La comparación con UCS-2

UCS-2 es una codificación de ancho fijo de 16 bits. Eso significa que solo se usa una unidad de código de 16 bits para representar un punto de código. En teoría, el UCS-2 puede representar 21 characters caracteres distintos, pero hay un giro.

BT Por cierto, estamos utilizando el término unidad de código en esta codificación de ancho fijo para comprender la relación entre UTF-16. En realidad, no hay tal cosa como unidad de código en cualquier fijo con codificación.

Dado que UCS sigue el conjunto de caracteres Unicode, la codificación de los caracteres en UCS – 2 es idéntica a la codificación de los caracteres en UTF-16 que se representan en una sola unidad de código.

Since Dado que UCS sigue el conjunto de caracteres Unicode, no puede codificar un carácter válido con los puntos de código reservados para los sustitutos.

En pocas palabras, UCS-2 contiene los caracteres del Plano Multilingüe Básico. Esta es la razón, algunos documentos antiguos y el software usaban codificación UCS-2. Pero la codificación UCS – 2 se ha vuelto obsoleta y se prefiere UTF-16.

Endianness y BOM

Como hemos comentado anteriormente, un documento codificado UTF en un nivel bajo contiene la secuencia de unidades de código. Para UTF-8, la unidad de código tiene 8 bits de longitud, mientras que para UTF-16, tiene 16 bits de longitud. Estas unidades de código conforman los caracteres.

Un decodificador UTF-8 o UTF-16 lee las unidades de código secuencialmente, una unidad de código a la vez para generar los caracteres.

Cada unidad de código representa un valor numérico que un decodificador UTF-8 o UTF-16 puede ver y decidir si es suficiente representar un carácter o sigue otras unidades de código que también deben considerarse.

Cuando se trata de UTF-8, las cosas son simples. Dado que cada unidad de código tiene 8 bits de longitud, convertir ese número binario de 8 bits en un valor numérico es rápido y fácil. Sin embargo, este no es el caso de UTF-16.

La unidad de código UTF-16 es un número binario de 16 bits (2 bytes) que representa un valor de punto de código. Generar el valor numérico a partir de múltiples bytes, en general, es complicado y los diferentes sistemas se comportan de manera diferente.

Este comportamiento depende de el peso del sistema. De nuestra discusión anterior sobre la endianidad, hay dos maneras en que podemos escribir un valor unitario de código UTF-16. Ya sea en formato Big-endian o en formato Little-endian.

En formato Big-endian, el MSB se almacena primero y el LSB se almacena el último. Hasta ahora, estamos escribiendo el valor de unidad de código UTF-16 en el formato Big-endian. Para escribir el valor unitario de código UTF-16 en Little-endian, necesitamos intercambiar bytes.

Hablemos de carácter character. A partir del ejemplo anterior, se puede representar en una sola unidad de código de UTF-16 y su codificación en representación hexadecimal se parece a 0906₁₆.

0906 is es un número de 16 bits con 09 como MSB y 06 como LSB. Por lo tanto, en la arquitectura Big-endian, se almacenará como 09 06. Sin embargo, en un Little-endian arquitectura, se almacenará como 06 09.

Por lo tanto, se convierte en nuestra responsabilidad codificar caracteres teniendo en cuenta la endianidad del sistema para que el sistema pueda leer un documento UTF-16 correctamente.

Pero, ¿cómo podemos saber de antemano si la máquina de un usuario es compatible con el documento codificado o no? Y dado que la endianidad de un sistema puede afectar la forma en que se decodifica un documento, ¿cómo lo compartimos públicamente?

Aquí es donde entra en escena la lista de materiales. Una Marca de Orden de bytes (BOM) es una secuencia de bytes que se agrega al principio de un archivo de texto o datos de texto.

Unicode recomienda caracteres con punto de código FEFF to para actuar como lista de materiales para codificaciones UTF-16 y UTF-32. Este carácter debe ser anterior al primer carácter del documento. Sin embargo, este carácter no será considerado por el decodificador en la salida.

Este carácter (U + FEFF) es un carácter de espacio sin ruptura de ancho cero (ZWNBSP) y es invisible. Por lo tanto, incluso si un decodificador no reconoce la lista de materiales, no producirá ninguna salida visible.

Este carácter se representa en una sola unidad de código de UTF-16 y en representación hexadecimal se ve como FE (MSB) y FF (LSB).

Por lo tanto, cuando los caracteres están codificados en formato Big-endian, necesitamos agregar FEFF como la lista de materiales al principio del archivo y cuando los caracteres están codificados en formato Little-endian, necesitamos agregar FFFE (reverso) como la lista de materiales al principio del archivo.

Unicode recomienda agregar la lista de materiales al documento codificado en UTF-16. Sin embargo, si falta la lista de materiales, se asume el formato Big-endian.

IANA prefiere UTF-16 como identificador para indicar un documento codificado en UTF-16. Sin embargo, UTF-16BE se usa para documentos codificados en formato Big-endian y UTF-16LE se usa para formato Little-endian.

Cuando se usa el nombre UTF-16BE o UTF-16LE, no se recomienda agregar la lista de materiales a un archivo. Incluso en este caso, si se agrega la lista de materiales, se considerará como un carácter ZWNBSP y no se ignorará.

names Los nombres UTF-16, UTF-16BE y UTF-16LE no distinguen entre mayúsculas y minúsculas.

Pros y contras

UTF-16 es eficiente porque tiene solo 2 unidades de código y, dado que la mayoría de los caracteres utilizados caen en el conjunto BMP, se pueden representar en una sola unidad de código. Sin embargo, viene con muchos problemas.

La mayor desventaja de UTF-16 es que no es compatible con ASCII. Dado que los caracteres ASCII están codificados con una sola unidad de código (número de 16 bits), un decodificador ASCII no puede decodificarlos correctamente.

UTF-16 consume espacio innecesario para caracteres ASCII. En comparación con el documento codificado en UTF-8 que contiene solo caracteres ASCII, el tamaño del mismo documento codificado en UTF-16 es dos veces mayor.

UTF-16 también se ve afectado por el peso del sistema. Si falta la lista de materiales y no se utiliza un identificador de codificación apropiado (como UTF-16LE), es posible que un documento codificado en UTF-16 no se decodifique correctamente.

Debido a la naturaleza de la codificación UTF-16, ha introducido puntos de código sustitutos que no pueden representar los caracteres válidos. Además, ha limitado el conjunto de caracteres Unicode a 10ffff last (último punto de código).

A pesar de estos hechos, algunos de los lenguajes de programación como JavaScript, Java, etc. y sistemas como Windows prefieren la codificación UTF-16.

Deja una respuesta

Tu dirección de correo electrónico no será publicada.