UTF-8: el estándar de la red

Quien lee una página en inglés o un correo electrónico en japonés no solo domina estos idiomas, sino que lo más probable es que también sea testigo de la marcha triunfal de UTF-8. “UTF-8” es la abreviatura de “8-bit UnicodeTransformation Format” y designa a la codificación de caracteres más extendida en la World Wide Web. El estándar internacional Unicode incluye tanto signos lingüísticos como elementos textuales de (casi) todos los idiomas, para el procesamiento electrónico de datos. Por ello, los códigos UTF-8 desempeñan para Unicode un papel fundamental.

El desarrollo de la codificación UTF-8

UTF-8 es una codificación de caracteres que le asigna una cadena de bits determinada, a cada carácter Unicode y que puede leerse como un número binario. Esto significa que UTF-8 asigna un número binario fijo a todas las consonantes, cifras y símbolos de un número cada vez mayor de idiomas. Los organismos internacionales para los que son importantes los estándares de Internet y que, por tanto, quieren establecer, están trabajando para hacer que UTF8 alcance un tamaño indiscutible para la codificación, entre otros, tanto el W3C como el Internet Engineering Task Force. De hecho, en el 2009, la mayoría de páginas web de todo el mundo ya estaban utilizando la codificación UTF-8. Según un informe de W3Techs, en marzo de 2018 el 90,9 % de todas las páginas web ya utilizaban esta codificación de caracteres.

Problemas anteriores a la introducción de UTF 8

Diferentes zonas con idiomas similares desarrollaron, en su momento, sus propios estándares de codificación debido a sus diferentes pretensiones. En los países de habla inglesa solo era necesario, por ejemplo, el código ASCII, cuya estructura permite asignar 128 caracteres a una cadena de caracteres legible por ordenador. Sin embargo, los caracteres asiáticos o el alfabeto cirílico utilizan más caracteres individuales únicos y algunos idiomas tienen caracteres que no existen en ASCII. Además, la asignación de diferentes codificaciones podía incluso duplicarse, lo que dio lugar a que, por ejemplo, un documento redactado en ruso se visualizara en un ordenador estadounidense con el sistema de caracteres latinos asignados al sistema, en lugar de con caracteres cirílicos. Las incoherencias resultantes dificultaron considerablemente la comunicación internacional.

Orígenes de UTF-8

Para solucionar esta problemática, Joseph D. Becker desarrolló para Xerox entre 1988 y 1991 el juego de caracteres universal Unicode. A partir de 1992, el consorcio industrial de TI X/Open también comenzó a buscar un sistema para sustituir a ASCII y así, ampliar el repertorio de caracteres, aunque la codificación tenía que seguir siendo compatible con ASCII. La primera codificación, que recibió el nombre de UCS-2, no cumplía con este requisito, pues transfería los números de caracteres en valores de 16 bits. UTF-1 también fracasó, en parte, por el conflicto de las asignaciones Unicode con las asignaciones de caracteres ASCII ya existentes. Como resultado, un servidor configurado basándose en ASCII ofrecía caracteres erróneos, lo que se convirtió en un problema considerable, puesto que en dicha época este era el sistema con el que trabajaban la mayoría de ordenadores en lengua inglesa. El siguiente avance fue el File System Safe UCS Transformation Format (FSS-UTF) de Dave Prosser, que eliminó la superposición con caracteres ASCII.

En agosto de ese mismo año, el borrador fue pasando por las manos de círculos expertos. En los Bell Labs, trabajaban en el sistema operativo Plan 9, los cofundadores de Unix Ken Thompson y Rob Pike, conocidos por haber obtenido varios Premios Nobel. Basándose en la idea de Prosser, desarrollaron una codificación autosincronizada (cada carácter indica los bits que necesita) y establecieron reglas para la asignación de las consonantes que podían representarse de forma distinta en el código (por ejemplo, “ü” como carácter único o “u + ¨”. De esta manera, utilizaron la codificación con éxito para su sistema operativo y se lo presentaron a las personas responsables. Así fue como se desarrolló FSS-UTF, hoy en día conocido como “UTF-8”.

Definición

UTF-8 es una codificación de caracteres de 8 bits para Unicode. La abreviatura “UTF-8” procede de “8-bit Unicode Transformation Format”, en español, formato de transformación Unicode de 8 bits. Se crea un número binario legible por ordenador que consta de uno a cuatro bytes, cada uno de los cuales está formado por ocho bits. Esta codificación se asigna a un carácter o a otro elemento textual. La estructura autosincronizada y la capacidad de generar 221 números binarios permite asignar de manera inconfundible todos y cada uno de los elementos lingüísticos y textuales de todos los idiomas del mundo.

UTF-8 en el juego de caracteres Unicode: un estándar para todos los idiomas

La codificación UTF-8 es un formato de transformación del estándar Unicode. El estándar internacional ISO 10646 define a Unicode a grandes rasgos con el nombre de “Universal Coded Character Set”. Los desarrolladores de Unicode, por su parte, delimitan ciertos parámetros para su aplicación práctica. No obstante, el estándar tiene como objeto garantizar la codificación uniforme y compatible a nivel internacional de caracteres y elementos textuales. Cuando se introdujo en 1991, Unicode estableció 24 sistemas de escritura y símbolos monetarios modernos para el procesamiento de datos y en 2017 ya había 139.

Hay diferentes formatos Unicode de transformación (UTF) capaces de reproducir los 1 114 112 puntos de código posibles. En concreto se han introducido tres formatos: UTF-8, UTF-16 y UTF-32. Otras codificaciones como UTF-7 o SCSU también tienen sus ventajas, pero no han sido capaces de establecerse.

Unicode se divide en 17 capas o niveles que comprenden 65 536 caracteres y cada nivel consta de 16 columnas y 16 filas. El primer nivel “Basic Multilingual Plane” (capa 0) comprende gran parte de los sistemas actuales de escritura a nivel mundial y también signos de puntuación, caracteres de control y símbolos. Actualmente se utilizan cinco capas adicionales:

  • Supplementary Multilingual Plane (capa 1): sistemas de escritura históricos, caracteres no muy utilizados
  • Supplementary Ideographic Plane (capa 2): caracteres CJK poco habituales (“Chinese, Japanese, Korean” (chino, japonés, coreano))
  • Supplementary SpecialPurpose Plane (capa 14): caracteres de control individuales
  • Supplementary Private Use Area – A (capa 15): uso privado
  • Supplementary Private Use Area – B (capa 16): uso privado

Los códigos UTF permiten acceder a todos los códigos Unicode y las características correspondientes se recomiendan para determinados campos de aplicación.

Las alternativas UTF-32 y UTF-16

UTF-32 siempre trabaja con 32 bits, es decir, 4 bytes y su estructura simple aumenta la legibilidad del formato. En los idiomas, en concreto los que tienen el alfabeto latino y solo utilizan los primeros 128 caracteres, la codificación utiliza más memoria de la necesaria (4 bytes en lugar de 1).

UTF-16 se estableció como formato de presentación en sistemas operativos como Apple macOS y Microsoft Windows. Sin embargo, también se aplica en muchos frameworks de desarrollo de software, siendo uno de los UTF más antiguos que todavía siguen utilizándose. Su estructura es especialmente apta para ahorrar espacio en la codificación de caracteres lingüísticos no latinos. La mayoría de caracteres se representan con 2 bytes (16 bits) y pocas veces se duplica la longitud a 4 bytes.

Eficiente y escalable: UTF-8

UTF-8 está compuesto por hasta cuatro cadenas de bits formadas por 8 bits respectivamente y su antecesor ASCII consta de una cadena con 7 bits. Ambas codificaciones definen los primeros caracteres codificados de forma congruente, pero lo esencial de los caracteres para la lengua inglesa es que están cubiertos por un byte. Para los idiomas con el alfabeto latino, este formato es el que utiliza el espacio de almacenamiento de la manera más eficiente posible, por lo que los sistemas operativos Unix y Linux lo utilizan de forma interna. El papel más importante de UTF-8 está relacionado con las aplicaciones de Internet a la hora de visualizar texto en la World Wide Web o en correos electrónicos.

Gracias a una estructura con capacidad para autosincronizarse, la legibilidad se mantiene a pesar de la longitud variable por carácter. Sin las restricciones de Unicode, UTF-8 permite asignar 231 (= 4 398 046 511 104) caracteres, pero con la limitación de 4 bytes de Unicode solo resultan efectivos 221, lo que es más que suficiente. El rango de Unicode tiene, además, capas vacías para muchos otros sistemas de escritura. La asignación exacta evita el solapamiento de puntos de código, que restringían la comunicación en el pasado. Mientras que UTF-16 y UTF-32 también permiten una asignación exacta, UTF-8 utiliza el espacio de almacenamiento para el sistema latino de un modo especialmente eficiente y está diseñado para que diferentes sistemas de escritura puedan coexistir sin problemas y para darles cobertura. Esto permite la visualización simultánea y significativa en campos de texto sin problemas de compatibilidad.

Aspectos básicos: la codificación UTF-8 y su composición

Por un lado, la codificación UTF-8 sorprende por la compatibilidad retrógrada con ASCII y, por otro, por una estructura capaz de autosincronizarse que les facilita a los desarrolladores la tarea de atisbar fuentes de error retrospectivamente. UTF utiliza solo 1 byte para todos los caracteres ASCII y el número total de cadenas de bits puede identificarse en las primeras cifras del número binario. Dado que el código ASCII solo comprende 7 bits, el código es 0. El 0 completa el espacio de memoria hasta llegar a un byte entero y señaliza el inicio de una cadena sin cadenas sucesivas. El nombre “UTF-8” se expresa, por ejemplo, como número binario con la codificación UTF-8 de la siguiente manera:

Carácter U T F - 8
UTF-8, binario 01010101 01010100 01000110 00101101 00111000
Punto de Unicode, hexadecimal U+0055 U+0054 U+0046 U+002D U+0038

La codificación UTF-8 les asigna una única cadena de bits a los caracteres ASCII como los empleados en la tabla. Los siguientes caracteres y símbolos dentro de Unicode tienen de dos a cuatro cadenas de 8 bits. La primera cadena recibe el nombre de byte de inicio y las cadenas siguientes son bytes sucesivos. Los bytes de inicio con bytes sucesivos siempre empiezan por 11 y los bytes sucesivos por 10. Si se busca un determinado punto en el código manualmente, puede reconocerse el principio de un carácter codificado con los marcadores 0 y 11. El primer carácter multibyte imprimible es el signo de exclamación invertido:

Carácter ¡
UTF-8, binario 11000010 10100001
Punto de Unicode, hexadecimal U+00A1

La codificación de prefijos evita que se codifique un carácter adicional en una cadena de bytes. Si una secuencia de bytes comienza a mitad de un documento, el ordenador seguirá mostrando los caracteres legibles, ya que no visualiza los caracteres incompletos. Si desde el principio buscas un carácter, la limitación de 4 bytes hará que no sea necesario que retrocedas en ningún punto más de tres cadenas de bytes para localizar el byte de inicio.

Otro elemento estructurador es que el número de unos al principio de un byte de inicio da cuenta de la longitud de la cadena de bytes. Como se puede observar arriba, 110xxxxx corresponde a 2 bytes, 1110xxxx a 3 bytes y 11110xxx a 4 bytes. En Unicode, el valor del byte asignado se corresponde con el número del carácter, lo que permite un orden léxico, aunque hay algunas brechas. El rango de Unicode comprendido entre U+007F y U+009F comprende números de control no asignados. Así, el estándar UTF-8 no asigna caracteres imprimibles, sino solo comandos.

Como ya se ha señalado, la codificación UTF-8 puede, en teoría, enlazar cadenas de hasta 8 bytes. Sin embargo, Unicode requiere una longitud de máximo 4 bytes. Esto tiene, por un lado, como consecuencia que las cadenas de bytes con 5 bytes o más no suelen ser válidas. Por otro, esta limitación es reflejo del afán de crear un código lo más compacto (con bajo consumo de memoria) y estructurado posible. Así, una norma fundamental al emplear UTF-8 es que siempre debe utilizarse la codificación más corta posible. La vocal ä se representa mediante 2 bytes como 11000011 10111100. En teoría también es posible combinar los puntos de código para la vocal u (01110101) y el carácter de la diéresis (11001100 10001000) para representar ä como 01110101 11001100 10001000. Esta forma, sin embargo, es considerada en UTF-8 como una codificación excesivamente larga y, por tanto, no es lícita.

Nota

Esta norma es la razón por la que están prohibidas las series de bytes que comienzan por 192 y 193, y es que representan a caracteres ASCII (0–127) con 2 bytes ya codificados con 1 byte.

Hay algunos rangos de valores de Unicode sin definir para UTF-8, pues estos se utilizan para los sustitutos de UTF-16. El cuadro siguiente muestra los bytes de UTF-8 permitidos según el grupo Internet Engineering Task Force (IETF) (en verde se muestran los bytes válidos y en rojo los no válidos).

Conversión de código Unicode hexadecimal a UTF-8 binario

Mientras que los ordenadores solo leen números binarios, las personas usan el sistema decimal. Una interfaz a medio camino entre estas formas es el sistema hexadecimal, que sirve de ayuda para representar cadenas de bits largas, para lo que utiliza cifras entre 0 y 9 y letras de la A a la F y actúa sobre la base del número 16. Como la cuarta potencia de 2, el sistema hexadecimal resulta más apto que el sistema decimal para representar rangos de bytes de 8 dígitos. Un dígito hexadecimal representa una cadena de cuatro caracteres (“nibble”) en un octeto. Un byte con ocho dígitos binarios también puede representarse con solo dos dígitos hexadecimales. Unicode utiliza el sistema hexadecimal para describir la posición de un carácter en el propio sistema y a partir de aquí pueden calcularse tanto el número binario como el punto de código de UTF-8.

En primer lugar, tiene que convertirse el número hexadecimal y después adaptar los puntos de código a la estructura de la codificación UTF-8. Para facilitar la estructuración puedes utilizar el siguiente cuadro, que muestra el número de puntos de código que tienen cabida en una cadena de bytes y la estructura que puede esperarse en un rango de valores de Unicode determinado.

Tamaño en bytes Bits libres para la determinación Primer punto de código de Unicode Último punto de código de Unicode Byte de inicio / byte 1 Byte sucesivo 2 Byte sucesivo 3 Byte sucesivo 4
1 7 U+0000 U+007F 0xxxxxxx      
2 11 U+0080 U+07FF 110xxxxx 10xxxxxx    
3 16 U+0800 U+FFFF 1110xxxx 10xxxxxx 10xxxxxx  
4 21 U+10000 U+10FFFF 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

En un área de código puede asumirse la cantidad de bytes empleados, pues se respeta el orden léxico en la enumeración de los puntos de código de Unicode y de los números binarios de UTF-8. En el rango U+0800 y U+FFFF UTF-8 emplea 3 bytes, por lo que hay disponibles 16 bits para expresar el punto de código de un símbolo. La inclusión de un número binario calculado en el esquema de UTF-8 tiene lugar de derecha a izquierda y los espacios en blanco a la izquierda deben completarse con ceros.

Ejemplo de cálculo:

El símboloᅢ(Hangul Junseong, Ä) se asocia en Unicode con U+1162. Para calcular el número binario es necesario convertir el número hexadecimal en un número decimal. Cada dígito del número se corresponde con la potencia correlativa de 16. La cifra derecha tiene el valor más bajo con 160 = 1. Empezando desde la derecha, multiplica el valor numérico de la cifra con el de la potencia y posteriormente añade los resultados.

2 * 1 = 2
6 * 16 = 96
1 * 256 = 256
1 * 4096 = 4096
4450 4450 4450 4450 4450

4450 es el número decimal calculado que tendrá que convertirse en un número binario. Para ello ha de dividirse por 2 hasta que el resultado sea 0. El valor Rest, escrito de derecha a izquierda, es el número binario.

4450 : 2 = 2225 Rest: 0
2225 : 2 = 1112 Rest: 1
1112 : 2 = 556 Rest: 0
556 : 2 = 278 Rest: 0
278 : 2 = 139 Rest: 0
139 : 2 = 69 Rest: 1
69 : 2 = 34 Rest: 1
34 : 2 = 17 Rest: 0
17 : 2 = 8 Rest: 1
8 : 2 = 4 Rest: 0
4 : 2 = 2 Rest: 0
2 : 2 = 1 Rest: 0
1 : 2 = 0 Rest: 1
Resultado: 1000101100010 Resultado: 1000101100010 Resultado: 1000101100010 Resultado: 1000101100010 Resultado: 1000101100010 Resultado: 1000101100010
Hexadecimal Binario
0 0000
1 0001
2 0010
3 0011
4 0100
5 0101
6 0110
7 0111
8 1000
9 1001
A 1010
B 1011
C 1100
D 1101
E 1110
F 1111

En este ejemplo tan detallado puedes seguir cada uno de los pasos del cálculo, pero si prefieres convertir números hexadecimales en números binarios de una manera sencilla y rápida, puedes reemplazar cada cifra hexadecimal por los cuatro dígitos binarios correspondientes.

Para el punto de código Unicode U+1162 introduce los dígitos como sigue:

x1 = b0001

x1 = b0001

x6 = b0110

x2 = b0010

x1162 = b0001000101100010

La codificación UTF-8 le ordena 3 bytes al punto de código U+1162, pues el punto de código se encuentra entre U+0800 y U+FFFF. El byte de inicio comienza por 1110 y los dos bytes sucesivos comienzan por 10. El número binario se añade en los bits libres de derecha a izquierda, que no especifican la estructura. A continuación se añade 0 en los otros bits del byte de inicio hasta completar el octeto. Tras ello, la codificación UTF-8 tiene el siguiente aspecto:

11100001 10000101 10100010 (el punto de código añadido se muestra en negrita)

Carácter Punto de código de Unicode, hexadecimal Número decimal Número binario UTF-8
U+1162 4450 1000101100010 11100001 10000101 10100010

UTF-8 en editores

UTF-8 es el estándar más utilizado en Internet. Sin embargo, algunos editores sencillos almacenan texto, pero no necesariamente en este formato. Microsoft Notepad, por ejemplo, utiliza normalmente una codificación conocida como “ANSI”, tras la que se esconde la codificación “Windows-1252” basada en ASCII. Para convertir un archivo de texto de Microsoft Word a UTF-8 (por ejemplo, para reproducir diferentes sistemas de escritura), sigue estos pasos: en “Guardar como” (“Save As”) selecciona la opción “Texto sin formato” (“Plain text”) en Tipo (“Save as type”).

A continuación se abre la ventana emergente “Conversión de archivo” (“File Conversion”). En “Codificación de texto” (“Text encoding”) selecciona el punto “Otra codificación” (“Other Encoding) y de la lista resultante elige la opción Unicode (UTF-8). En el menú desplegable Terminar líneas con (“End lines with”) selecciona Retorno de carro / Avance de línea (“Carriage return/cell feed”). Así de sencillo es convertir un archivo en el juego de caracteres Unicode con UTF-8.

Abrir un archivo de texto sin marcar en el que no se sepa de antemano el tipo de codificación utilizado puede ocasionar problemas de edición. En tales casos, Unicode permite recurrir a la “marca de orden de bytes” (Byte Order Mark o BOM). Con este carácter se puede mostrar si el documento tiene formato big endian o little endian. Si un programa decodifica un archivo en UTF-16 little endian con ayuda de UTF-16 big endian, el texto resultante se muestra lleno de errores. Sin embargo, los documentos basados en el conjunto de caracteres UTF-8 no tienen este problema, pues la cadena de bytes siempre se lee como una secuencia big endian. La BOM muestra en este caso que el documento existente está codificado con UTF-8.

Nota

En algunas codificaciones (UTF-16 y UTF-32), los caracteres que se visualizan con más de un byte pueden presentar el byte más relevante en posición delantera (izquierda) o trasera (derecha). Si el byte más importante (“Most Significant Byte”, MSB) está delante, se añade “big endian” a la codificación, pero si está detrás “little endian”.

La BOM se coloca antes de un flujo de datos o al principio de un archivo. Dicha marca tiene prioridad sobre el resto de instrucciones e incluso sobre la cabecera HTTP, pues actúa como un tipo de firma para códigos Unicode y tiene el punto de código U+FEFF. La BOM se presenta de forma diferente en formato codificado en función de la codificación utilizada.

Formato de codificación BOM, codepoint: U+FEFF (hex.)
UTF-8 EF BB BF
UTF-16 big-endian FE FF
UTF-16 little-endian FF FE
UTF-32 big-endian 00 00 FE FF
UTF-32 little-endian FF FE 00 00

La Byte Order Mark no debe utilizarse si el protocolo lo prohíbe explícitamente o si a los datos ya se les ha asignado un tipo determinado. Según el protocolo, algunos programas requieren caracteres ASCII. Debido a que UTF-8 es compatible retroactivamente con la codificación ASCII y define su propia secuencia de bytes, no se necesita ninguna BOM. De hecho, Unicode recomienda no utilizar la BOM en UTF-8, pero debido a que puede existir una BOM en el código antiguo y esto puede acarrear problemas, es importante identificar como tal, a la marca de orden de bytes existente.

En resumen: la codificación UTF-8 mejora la comunicación internacional

UTF-8 tiene muchas ventajas y estas no se limitan a que la codificación sea compatible retrospectivamente con ASCII. Mediante su secuencia de bytes variable y la enorme cantidad de puntos de código posibles es capaz de representar un número sumamente grande de sistemas de escritura, por lo que el volumen de memoria se utiliza de manera eficiente.

La introducción de estándares uniformes simplifica la comunicación internacional. Gracias a que se recurre a secuencias de bytes capaces de autosincronizarse, la codificación UTF-8 destaca por un porcentaje de errores muy bajo en la visualización de caracteres. Si surgen errores en la codificación o en la transmisión, estos pueden encontrarse fácilmente al principio de cada carácter ,mediante la localización del byte de la secuencia que comienza por 0 u 11. En las páginas web, UTF-8 es, con una tasa de utilización de más del 90 %, el estándar de codificación indiscutible.

¿Le ha resultado útil este artículo?
Page top