UTF-8 (abreviatura de Universal Character Set Transformation Format - 8 bits ) es una codificación de caracteres de computadora diseñada para codificar el conjunto de caracteres del "repertorio de caracteres codificados universal", desarrollado originalmente por ISO en la norma internacional ISO / IEC 10646 , ahora es totalmente compatible con el estándar Unicode , sin dejar de ser compatible con el estándar ASCII limitado al inglés básico, pero ampliamente utilizado durante décadas.
UTF-8 es utilizado por el 82,2% de los sitios web en diciembre 2014, 87,6% en 2016, 90,5% en 2017, 93,1% en febrero de 2019 y casi el 95,2% en octubre 2020. Por su naturaleza, UTF-8 se utiliza cada vez más en Internet y en sistemas que necesitan intercambiar información. También es la codificación más utilizada en GNU , Linux y sistemas compatibles para gestionar textos y sus traducciones de la forma más sencilla posible en todos los sistemas de escritura y alfabetos del mundo.
UTF-8 es un "formato de transformación" originalmente del trabajo para el estándar ISO / IEC 10646 , es decir, UTF-8 define una codificación para cualquier punto de código escalar ( carácter abstracto o "no carácter") del Conjunto de caracteres universal ( UCS ) directorio. Este directorio ahora es común al estándar ISO / IEC 10646 (desde su revisión 1) y al estándar Unicode (desde su versión 1.1).
UTF-8 se define oficialmente en el estándar ISO / IEC 10646 desde su adopción en una enmienda publicada en 1996. También se describió en el estándar Unicode y ha sido parte de este estándar desde la versión 3.0 publicada en 2000. En 1996 se publicó el RFC 2044 (" UTF-8, un formato de transformación de ISO 10646 ") con el fin de proporcionar una especificación accesible de UTF-8 y comenzar su estandarización dentro del Grupo de Trabajo de Ingeniería de Internet (IETF). Esta RFC fue revisada en 1998 ( RFC 2279) y finalmente en 2003 ( RFC 3629), esta última versión convierte a UTF-8 en uno de los estándares de Internet (STD 63).
Técnicamente, esto implica codificar caracteres Unicode en forma de secuencias de uno a cuatro puntos de código de un byte cada una. El estándar Unicode define, entre otras cosas, un conjunto (o directorio) de caracteres. Cada carácter se identifica en este conjunto por un índice completo también llamado " punto de código ". Por ejemplo, el carácter “€” ( euros ) es el 8365 º carácter del directorio de Unicode, su índice o punto de código, por lo tanto, 8364 (0x20AC) (empezamos a contar desde 0) es.
El directorio Unicode puede contener más de un millón de caracteres, que es demasiado grande para codificarse como un solo byte (limitado a valores entre 0 y 255). Por lo tanto, el estándar Unicode define métodos estandarizados para codificar y almacenar este índice en forma de una secuencia de bytes: UTF-8 es uno de ellos, junto con UTF-16 , UTF-32 y sus diversas variantes.
La principal característica de UTF-8 es que es retrocompatible con el estándar ASCII, es decir que cualquier carácter ASCII está codificado en UTF-8 en forma de un solo byte, idéntico al código ASCII. Por ejemplo, "A" (A mayúscula) tiene el código ASCII 65 (0x41) y está codificado en UTF-8 por el byte 65. Cada carácter cuyo punto de código es mayor que 127 (0x7F) (carácter no ASCII) es código en 2 a 4 bytes . El carácter "€" (euro) se codifica, por ejemplo, en 3 bytes : 226, 130 y 172 (0xE2, 0x82 y 0xAC).
El número (valor escalar) de cada punto de código en el Conjunto de caracteres universal (UCS) viene dado por la norma ISO / IEC 10646 que asigna un punto de código a cada carácter válido y permite su codificación asignando un valor escalar idéntico al punto de código. ; este estándar está incluido en el estándar Unicode (que usa el mismo directorio desde la versión 1.1).
Todos los " puntos de código " de U + 0000 a U + D7FF y de U + E000 a U + 10FFFF son representables en UTF-8, incluso los asignados a "no caracteres" ( sin carácter ) y todos los que aún no están asignados. y solo esos. Los únicos puntos de código válidos en el espacio UCS y que no deben representarse en UTF-8 son los asignados a los " half-codepoints " ( sustitutos en inglés), porque no son representables de alguna manera. Bijective en la codificación UTF-16 y tampoco son caracteres por sí mismos: a diferencia de otros puntos de código, los semicódigos, por lo tanto, no tienen un " valor escalar " definido.
Les points de code ayant une valeur scalaire de 0 à 127 (points de codes U+0000 à U+007F, attribués aux caractères du jeu codé sur 7 bits dans l'ASCII) sont codés sur un seul octet dont le bit de poids fort es nulo.
Los otros puntos de código (asignados o no a caracteres) que tienen un valor escalar superior a 127 (excepto aquellos a los que se les asignan "semicódigos" que no son en sí mismos caracteres) se codifican en varios bytes, cada uno con su propio valor distinto de cero. bit más significativo: los bits más significativos del primer byte de la secuencia codificada forman una secuencia de unos de longitud igual al número total de bytes (al menos 2) usados para toda la secuencia seguida de un 0 y los bytes subsiguientes requeridos tienen sus dos bits más significativos se establecen en 10.
Caracteres codificados | Representación binaria UTF-8 | Primer byte válido (hexadecimal) | Significado |
---|---|---|---|
U + 0000 hasta U + 007F | 0 xxxxxxx | 00 a 7F | 1 byte, codificación de 7 bits |
U + 0080 hasta U + 07FF | 11 0 xxxxx 10 xxxxxx | C2 a DF | 2 bytes, codificación de 11 bits |
U + 0800 a U + FFFF | 111 0 xxxx 10 xxxxxx 10 xxxxxx | E0 a EF | 3 bytes, codificación de 16 bits |
U + 10000 a U + 10FFFF | 1111 0 xxx 10 xxxxxx 10 xxxxxx 10 xxxxxx | F0 a F4 | 4 bytes, codificación de 21 bits |
Este principio podría extenderse a ocho bytes para un solo punto de código (para representar puntos de código de hasta 42 bits), pero la versión estandarizada actual de UTF-8 establece el límite en cuatro.
La codificación prohíbe la representación de puntos de código reservados para semicódigos (que no tienen un valor escalar definido, con el fin de preservar la compatibilidad con UTF-16 que tampoco permite representarlos). Sin embargo, autoriza la representación de puntos de código asignados a no caracteres (aunque su presencia esté prohibida en un texto conforme).
Tipo | Personaje |
Punto de código (hexadecimal) |
Valor escalar | Codificación UTF-8 | ||
---|---|---|---|---|---|---|
decimal | binario | binario | hexadecimal | |||
Control | [NO] | U + 0000 | 0 | 0 | 0 0000000 | 00 |
[NOSOTROS] | U + 001F | 31 | 1111 | 0 0011111 | 1F | |
Texto | [SP] | U + 0020 | 32 | 100000 | 0 0100000 | 20 |
A | U + 0041 | sesenta y cinco | 100.0001 | 0 100.0001 | 41 | |
~ | U + 007E | 126 | 111 1110 | 0 1111110 | 7E | |
Control | [DEL] | U + 007F | 127 | 111 1111 | 0 1111111 | 7F |
[ALMOHADILLA] | U + 0080 | 128 | 000 1000 0000 | 110 000 10 10 000 000 | C2 80 | |
[APC] | U + 009F | 159 | 000 1001 1111 | 110 000 10 10 011 111 | C2 9F | |
Texto | [NBSP] | U + 00A0 | 160 | 000 1010 0000 | 110 000 10 10 100 000 | C2 A0 |
mi | U + 00E9 | 233 | 000 1110 1001 | 110 000 11 10 101 001 | C3 A9 | |
߿ | U + 07FF | 2047 | 111 1111 1111 | 110 111 11 10 111 111 | DF BF | |
ࠀ | U + 0800 | 2048 | 1000 0000 0000 | 1110 0000 10 1000 00 10 000000 | E0 A0 80 | |
€ | U + 20AC | 8 364 | 100000 10101100 | 1110 0010 10 0000 10 10 101100 | E2 82 AC | |
| U + D7FF | 55,295 | 1101 0111 1111 1111 | 1110 1101 10 0111 11 10 111111 | ED 9F BF | |
Medio codet | U + D800 | (nada) | (codificación prohibida) | |||
U + DFFF | ||||||
Uso privado | [] | U + E000 | 57,344 | 1110 0000 0000 0000 | 1110 1110 10 0000 00 10 0000000 | EE 80 80 |
[] | U + F8FF | 63,743 | 1111 1000 1111 1111 | 1110 1111 10 1000 11 10 111111 | EF A3 BF | |
Texto | U + F900 | 63 744 | 1111 1001 0000 0000 | 1110 1111 10 1001 00 10 000 000 | EF A4 80 | |
﷏ | U + FDCF | 64 975 | 1111 1101 1100 1111 | 1110 1111 10 1101 11 10 001111 | EF B7 8F | |
No personajes | U + FDD0 | 64 976 | 1111 1101 1101 0000 | 1110 1111 10 1101 11 10 010000 | EF B7 90 | |
U + FDEF | 65,007 | 1111 1101 1110 1111 | 1110 1111 10 1101 11 10 101111 | EF B7 AF | ||
Texto | ﷰ | U + FDF0 | 65,008 | 1111 1101 1111 0000 | 1110 1111 10 1101 11 10 110000 | EF B7 B0 |
U + FFFD | 65.533 | 1111 1111 1111 1101 | 1110 1111 10 1111 11 10 111101 | EF BF BD | ||
No personajes | U + FFFE | 65,534 | 1111 1111 1111 1110 | 1110 1111 10 1111 11 10 111110 | EF BF BE | |
U + FFFF | 65.535 | 1111 1111 1111 1111 | 1110 1111 10 1111 11 10 111111 | EF BF BF | ||
Texto | ? | U + 10,000 | 65,536 | 1 0000 0000 0000 0000 | 11 110 000 10 01 0000 10 0000 00 10 000000 | F0 90 80 80 |
? | U + 1D11E | 119.070 | 1 1101 0001 0001 1110 | 110 11 000 10 01 1101 10 0001 00 10 011 110 | F0 9D 84 9E | |
? | U + 1FFFD | 131.069 | 1 1111 1111 1111 1101 | 11110 000 10 01 1111 10 1111 11 10 111 101 | F0 9F BF BD | |
No personajes | U + 1FFFE | 131.070 | 1 1111 1111 1111 1110 | 11110 000 10 01 1111 10 1111 11 10 111 110 | F0 9F BF BE | |
U + 1FFFF | 131,071 | 1 1111 1111 1111 1111 | 11 110 000 10 01 1111 10 1111 11 10 111111 | F0 9F BF BF | ||
Texto | ? | U + 20.000 | 131.072 | 10 0000 0000 0000 0000 | 11 110 000 10 10 0000 10 0000 00 10 000000 | F0 A0 80 80 |
? | U + 2FFFD | 196,605 | 10 1111 1111 1111 1101 | 11,110 000 10 10 1111 10 1111 11 10 111 101 | F0 AF BF BD | |
No personajes | U + 2FFFE | 196,606 | 10 1111 1111 1111 1110 | 11.110 000 10 10 1111 10 1111 11 10 111 110 | F0 AF BF BE | |
U + 2FFFF | 196,607 | 10 1111 1111 1111 1111 | 11 110 000 10 10 1111 10 1111 11 10 111111 | F0 AF BF BF | ||
... otros planes reservados ... | ||||||
Especiales | ? | U + E0000 | 917.504 | 1110 0000 0000 0000 0000 | 11110 011 10 10 0000 10 0000 00 10 000000 | F3 A0 80 80 |
? | U + EFFFD | 983,037 | 1110 1111 1111 1111 1101 | 11110 011 10 10 1111 10 1111 11 10 111101 | F3 AF BF BD | |
No personajes | U + EFFFE | 983,038 | 1110 1111 1111 1111 1110 | 11110 011 10 10 1111 10 1111 11 10 111110 | F3 AF BF BE | |
U + EFFFF | 983,039 | 1110 1111 1111 1111 1111 | 11110 011 10 10 1111 10 1111 11 10 111111 | F3 AF BF BF | ||
Uso privado | [?] | U + F0000 | 983,040 | 1111 0000 0000 0000 0000 | 11110 011 10 11 0000 10 0000 00 10 000000 | F3 B0 80 80 |
[ ] | U + FFFFD | 1.048.573 | 1111 1111 1111 1111 1101 | 11110 011 10 11 1111 10 1111 11 10 111101 | F3 BF BF BD | |
No personajes | U + FFFFE | 1.048.574 | 1111 1111 1111 1111 1110 | 11110 011 10 11 1111 10 1111 11 10 111110 | F3 BF BF BE | |
U + FFFFF | 1.048.575 | 1111 1111 1111 1111 1111 | 11110 011 10 11 1111 10 1111 11 10 111111 | F3 BF BF BF | ||
Uso privado | [?] | U + 100.000 | 1.048.576 | 1 0000 0000 0000 0000 0000 | 11110 100 10 00 0000 10 0000 00 10 000000 | F4 80 80 80 |
[?] | U + 10FFFD | 1,114,109 | 1 0000 1111 1111 1111 1101 | 11110 100 10 00 1111 10 1111 11 10 111101 | F4 8F BF BD | |
No personajes | U + 10FFFE | 1,114,110 | 1 0000 1111 1111 1111 1110 | 11110 100 10 00 1111 10 1111 11 10 111110 | F4 8F BF BE | |
U + 10FFFF | 1,114,111 | 1 0000 1111 1111 1111 1111 | 11110 100 10 00 1111 10 1111 11 10 111111 | F4 8F BF BF |
En cualquier cadena de caracteres codificada en UTF-8, notamos que:
El punto más importante de código válido que se puede asignar a un carácter válido que no es privado es U + EFFFD en el 15 ° Plan (aún no está asignado pero puede convertirse en el futuro), pero UTF-8 también se puede usar, de manera estándar, para representar cualquier carácter válido para uso privado (en uno de los tres rangos U + E000 a U + F8FF, U + F0000 a U + FFFFD y U + 100000 a U + 10FFFD).
La aceptación o no de caracteres que no sean caracteres o de uso privado se deja a las aplicaciones o protocolos de transporte de texto. Sin embargo, los no caracteres no se aceptan normalmente en textos que se ajustan estrictamente al estándar Unicode o al estándar ISO / IEC 10646 .
Algunas aplicaciones imponen restricciones adicionales sobre los puntos de código que se pueden utilizar (por ejemplo, los estándares HTML y XML prohíben, en cualquier documento conforme a estas especificaciones, la presencia de la mayoría de los caracteres de control entre U + 0000 y U + 001F y entre U + 0080 y U + 009F, fuera de la pestaña U + 0009, el control se considera un carácter en blanco y también prohíbe los no caracteres ).
Cualquier punto de código siempre está representado exactamente por la misma secuencia binaria, cualquiera que sea su posición relativa en el texto, y estas secuencias se sincronizan automáticamente en la posición indivisa de los puntos de código significativos (aquí los bytes: siempre podemos saber si un byte comienza o no un secuencia binaria efectiva); por lo tanto, esta codificación permite algoritmos de búsqueda de texto rápidos, como el algoritmo de Boyer-Moore .
Este no es siempre el caso de las codificaciones contextuales (que generalmente utilizan compresión de datos , por ejemplo, SCSU definida en la nota técnica opcional del estándar UTS # 6 que complementa el estándar Unicode) y que pueden requerir la lectura completa del texto desde el principio., Ni codificaciones basadas en más de una variable de estado (o que incorporen códigos de redundancia adicionales); en el mejor de los casos, algunas de estas codificaciones pueden requerir el uso de algoritmos de resincronización complejos, a menudo basados en heurísticas que pueden fallar o dar lugar a interpretaciones falsas si el texto no se lee desde el principio (por ejemplo, BOCU -1).
Principio y singularidad de la codificaciónEn la tabla anterior, vemos que el carácter “€” se encuentra en el punto de código U + 20AC, ya sea en decimal 8364, o en binario: 100,000 10101100.
Este último número tiene dígitos binarios significativos, por lo que se necesitan al menos 14 bits para codificar el carácter "€". El estándar presentado anteriormente en realidad requiere tres bytes para representar estos caracteres.
Con cuatro bytes disponibles, sería posible colocar de acuerdo con este estándar hasta 21 bits , por lo que en particular, representar el carácter “€” por 00000 00 100000 10101100, agregando 7 ceros a la izquierda . Sin embargo, el estándar impone que un programa que decodifica UTF-8 no debe aceptar cadenas de bytes innecesariamente largas como en este ejemplo, por razones de seguridad (evite el uso de pruebas de subcadenas demasiado tolerantes). Así, “€” se codificará: 11100010 10000010 10101100, pero la codificación 11110000 10000010 10000010 10101100, deducida de la representación de “€” en 21 bits , aunque inequívoca, no debe utilizarse.
Una forma tan larga de lo necesario se llama demasiado larga en inglés . Dichos formularios (inicialmente autorizados en especificaciones antiguas antes de que fueran estandarizados sucesivamente por el RFC inicial publicado por el X / Open Consortium , luego en paralelo por el estándar ISO 10646 y el estándar Unicode) están prohibidos y deben tratarse como inválidos.
La codificación es predictiva y siempre permite encontrar la posición del primer byte de una secuencia que representa un punto de código, a partir del valor de cualquier byte y de la lectura de un número limitado de bytes vecinos, en las dos direcciones de lectura (it siempre será el propio byte, o el primero elegible en uno de los 1 a 3 bytes vecinos).
Se dice que tales secuencias están mal formadas . (Consulte la referencia anterior, especialmente la segunda tabla en la cláusula de conformidad D36 del estándar o del artículo Unicode ).
Por otro lado, los puntos de código reservados (aún no asignados a los caracteres) están autorizados (incluso si la interpretación de los caracteres puede seguir siendo ambigua): corresponde a las aplicaciones decidir si estos caracteres son aceptables o no, sabiendo que los mismos es probable que se sigan utilizando aplicaciones aunque estas posiciones se hayan asignado en los estándares Unicode e ISO 10646 a caracteres nuevos y completamente válidos.
De manera similar, otros puntos de código asignados permanentemente a otros " no caracteres " están prohibidos en textos que cumplen con ISO / IEC 10646 o con el estándar Unicode : por ejemplo, U + x FFFE a U + x FFFF (donde x indica un número de plan hexadecimal de 0 a 10). Pero siguen siendo codificables y decodificables como tales en UTF-8 (los no caracteres están disponibles para aplicaciones que pueden hacer uso de ellos dentro de las API internas, por ejemplo, como códigos intermedios necesarios para la implementación de ciertos procesos).
La restricción del espacio de representación a solo los puntos de código menores o iguales a U + 10FFFF (sin incluir los puntos de código asignados a los puntos de medio código ) no siempre se ha aplicado:
Un texto en US-ASCII se codifica de forma idéntica en UTF-8 (cuando no se utiliza la lista de materiales ).
Debido a que un carácter se divide en una secuencia de bytes (no palabras de varios bytes), no hay problema de endianness ( endianness en inglés).
Para la mayoría de los lenguajes de escritura latina, archivos de datos digitales o códigos fuente de programas, o muchos protocolos de comunicación textual (como FTP , HTTP o MIME ), que utilizan caracteres de forma extensiva (oa veces solo en partes) US-ASCII, UTF-8 requiere menos bytes que UTF-16 o UTF-32 .
Muchas técnicas de programación de computadoras que son válidas con caracteres uniformes de un solo byte siguen siendo válidas con UTF-8, que incluyen:
Esta es una codificación que se sincroniza automáticamente (leyendo un solo byte sabemos si es el primero de un carácter o no).
Los puntos de código se representan en UTF-8 mediante secuencias de bytes de diferentes tamaños (así como en UTF-16), lo que hace que algunas operaciones en cadenas de puntos de código sean más complicadas: calcular el número de puntos de código; posicionamiento a una distancia dada (expresada en número de puntos de código) en un archivo de texto y en general cualquier operación que requiera acceso al punto de código de la posición N en una cadena.
Un tamaño variable de los caracteres de una cadena impide el uso de algoritmos eficientes en términos de comparación de cadenas, como el algoritmo Knuth-Morris-Pratt y, por lo tanto, penaliza fuertemente el procesamiento masivo de datos como en las bases de datos de explotación. Sin embargo, este problema está más relacionado con aspectos de estandarización que de codificación.
Para los idiomas que usan muchos caracteres fuera de US-ASCII , UTF-8 ocupa mucho más espacio. Por ejemplo, los ideogramas habituales que se utilizan en textos en idiomas asiáticos como el chino o el japonés ( kanji , por ejemplo) utilizan 3 bytes en UTF-8 frente a 2 bytes en UTF-16.
En general, las escrituras que usan muchos puntos de código de valor igual o mayor que U + 0800 ocupan más memoria que si estuvieran codificadas con UTF-16 (UTF-32 será más eficiente solo para textos que usen principalmente escrituras. antiguo o raro codificado fuera del plan multilingüe básico, es decir desde U + 10000, pero también puede resultar útil localmente en determinados procesos para simplificar los algoritmos, pues los caracteres allí siempre tienen un tamaño fijo, convirtiendo entrada o salida datos desde o hacia UTF-8 o UTF-16 son triviales).
Por su sistema de codificación, era posible representar un código de diferentes formas en UTF-8, lo que podría plantear un problema de seguridad: un programa mal escrito puede aceptar un cierto número de representaciones UTF-8, normalmente inválidas según el RFC 3629 y en las especificaciones (ahora equivalentes entre sí) publicadas por ISO 10646 y Unicode; pero este no era el caso de acuerdo con la especificación original, lo que permitía convertirlos como un solo carácter.
Ainsi, un logiciel détectant certaines chaînes de caractères (pour prévenir les injections SQL , par exemple) pouvait échouer dans sa tâche (ce n'est plus le cas si la conformité du codage avec la définition stricte et normalisée d'UTF-8 est vérifiée Ante todo).
Tomemos un ejemplo de un caso real de un virus que atacó servidores HTTP en la Web en 2001 ( (en) Crypto-Gram: 15 de julio de 2000 Microsoft IIS y PWS Extended Unicode Directory Traversal Vulnerability Microsoft IIS 4.0 / 5.0 Web Directory Traversal Vulnerability ) . Una secuencia a detectar podría estar representada en ASCII ( a fortiori en UTF-8) por los bytes “ 2F 2E 2E 2F ” en notación hexadecimal . Sin embargo, una forma incorrecta de codificar esta cadena en UTF-8 sería " 2F C0 AE 2E 2F ", también llamada forma demasiado larga . Si el software no se escribe cuidadosamente para rechazar esta cadena, por ejemplo, poniéndola en forma canónica , se abre una posible brecha de seguridad. Este ataque se llama cruce de directorio .
El software que acepta texto codificado en UTF-8 ha sido protegido para rechazar sistemáticamente estas formas largas porque no cumplen con el estándar: o se rechaza el texto completo; pero a veces las secuencias no válidas se reemplazan por un carácter de sustitución (generalmente U + FFFD si la aplicación acepta y procesa este carácter normalmente; a veces un signo de interrogación o el carácter de control de sustitución SUB U + 001A de ASCII, que pueden plantear otros problemas de compatibilidad); con menos frecuencia, estas secuencias prohibidas se eliminan silenciosamente (lo que se recomienda muy poco).
UTF-8 solo puede representar el carácter de control nulo (U + 0000) con un solo byte nulo, lo que plantea problemas de compatibilidad con el procesamiento de cadenas que no codifican por separado su longitud efectiva porque este byte nulo no representa entonces ningún carácter sino el fin de la cadena (caso muy común en lenguaje C o C ++ y en las API de los sistemas operativos). Si un carácter nulo debe ser almacenado en un texto en dichos sistemas, será necesario recurrir a un sistema de escape, específico para este idioma o sistema antes de codificar en UTF-8 el texto así transformado. En la práctica, ningún texto válido debería contener este carácter. Otra solución es utilizar una de las secuencias prohibidas en la codificación estándar UTF-8 para codificar el carácter por esta secuencia; pero el texto así codificado no se ajustará a la codificación UTF-8 estándar, incluso si la codificación así modificada sigue siendo un formato de transformación universal conforme (que, sin embargo, no debería designarse como "UTF-8"). Consulte la sección siguiente sobre variantes no estándar basadas en UTF-8.
El uso de UTF8, como cualquier codificación de tono variable, en una base de datos plantea múltiples problemas de rendimiento.
Las operaciones de comparación (=,>, <, BETWEEN, LIKE ...), ordenar (ORDER BY), agrupar (GROUP BY), como las operaciones de deduplicación (DISTINCT) basadas en la semántica de la información, son imposibles de gestionar directamente en UTF8 .
De hecho, para las cadenas de caracteres que comprenden el mismo número de letras (por ejemplo, CHAR (8)), el número de bytes puede ser diferente (en particular debido a los caracteres diacríticos: acentos, ligadura ...), los algoritmos utilizados deben, por en su mayor parte, realizar una alineación antes de poder operar, lo que induce un costo de procesamiento adicional nada despreciable.
Por ejemplo, el DBMS MySQL / MariaDB ha optado por representar los caracteres de las cadenas presentadas como UTF8 utilizando sistemáticamente 3 bytes por carácter. Las consecuencias son las siguientes: triplicar el volumen de datos y dividir por tres la longitud potencial de las claves de índice en comparación con la codificación ASCII, y alargar los tiempos de ejecución para comparaciones, ordenamientos, agrupaciones o deduplicaciones. La cadena finalmente se devuelve en formato UTF8 después de limpiar los bytes innecesarios.
Otros DBMS como Microsoft SQL Server han optado por comprimir el soporte UTF8 insertando los caracteres adicionales en una codificación de 2 bytes, basada en UNICODE aprovechando los espacios que deja la especificación en blanco. El esfuerzo adicional para la traducción a UTF8 solo radica en la recodificación de los caracteres codificados en 2 bytes y la expansión de los codificados en 3.
UTF-8 fue inventado por Kenneth Thompson durante una cena con Rob Pike alrededorSeptiembre de 1992. Entonces , llamado FSS-UTF , se usó inmediatamente en el sistema operativo Plan 9 en el que estaban trabajando. Una restricción a resolver fue codificar los caracteres nulos y '/' como en ASCII y que ningún byte que codifique otro carácter tenga el mismo código. Por lo tanto, los sistemas operativos UNIX podrían continuar buscando estos dos caracteres en una cadena sin adaptación de software.
FSS-UTF fue objeto de un estándar X / Open preliminar de 1993 que se propuso a ISO. Este último lo adoptó como parte del estándar ISO / IEC 10646 bajo el nombre primero de UTF-2, luego finalmente UTF-8.
Gráfico que muestra el uso de UTF-8 (azul claro) que supera otras codificaciones de caracteres de texto importantes en la Web. En 2010, la prevalencia de UTF-8 era de alrededor del 50%, pero en 2016 era más del 90%. |
Estadísticas que reflejan las tecnologías utilizadas en los sitios web determinadas a partir de técnicas de reconocimiento para diferentes patrones, incluidos elementos HTML, etiquetas HTML específicas (como la "metaetiqueta del generador", el código JavaScript, el código CSS, la estructura de las URL del sitio, enlaces fuera del sitio, encabezados HTTP, por ejemplo, cookies, respuestas HTTP a determinadas solicitudes, como la compresión.
Estadísticas basadas en una muestra de los 10 millones de sitios web principales según Alexa. El total no llega al 100% porque algunos servidores utilizan más de una tecnología. |
Fuente w3techs |
La codificación FSS-UTF original estaba destinada a reemplazar la codificación multibyte UTF-1 propuesta inicialmente por ISO 10646. Esta codificación inicialmente permisiva permitía varias representaciones binarias para el mismo carácter (esto estaba prohibido en la versión estandarizada de la RFC publicada por X / Open Consortium, y respaldado por Kenneth Thompson).
Además, podría (en una versión preliminar no retenida) codificar todos los caracteres cuyo valor de punto de código comprendiera hasta 32 bits definiendo un octavo tipo de byte (en secuencias que comprenden hasta 6 bytes ), en el lugar de los 7 tipos de bytes finalmente retenidos para codificar (en secuencias que también comprenden hasta 6 bytes ) solo el código apunta hasta 31 bits en la versión inicial de UTF-8 (publicado por el Consorcio X / Open bajo el nombre FSS-UTF, luego propuesto por el comité técnico de ISO 10646 como la propuesta “UTF-2”, entonces todavía compite con la propuesta “UTF-1”, hasta que la propuesta UTF-2 sea retenida y adopte el nombre UTF-8 ya retenido y usado en X / Open y Plan 9).
Esta codificación UTF-8 se restringió aún más cuando Unicode e ISO 10646 acordaron asignar caracteres solo en los primeros 17 planos para mantener la compatibilidad con UTF-16 indefinidamente (sin tener que modificarlo), restringiendo las secuencias hasta 'a solo 4 bytes y usando solo los primeros 5 de los 7 tipos de bytes (que requirieron definir como no válidos nuevos valores de bytes y ciertas secuencias de bytes, aunque sean válidas individualmente).
El IETF ahora requiere que UTF-8 sea soportado por defecto (y no simplemente como una extensión soportada) por todos los nuevos protocolos de comunicación de Internet (publicados en su RFC numerados) que intercambian texto (los protocolos más antiguos, sin embargo, no han sido modificados Hacer este soporte obligatorio, pero solo extendido si es posible, soportarlo opcionalmente, si esto produce incompatibilidades o introduce nuevos riesgos de seguridad: este es el caso de los protocolos de Internet ampliamente utilizados como DNS , HTTP , FTP , Telnet y HTML en sus versiones iniciales. entonces aún no estandarizado por W3C e ISO).
Se ha vuelto imprescindible, especialmente en el principal software de comunicación web y en los sistemas operativos actuales:
Sin embargo, se siguieron utilizando variantes de UTF-8 (basadas en las posibilidades de codificación de la versión inicial sin restricciones) (especialmente en la implementación de la serialización de cadenas de Java) para permitir la codificación como un escape multibyte de ciertos caracteres ASCII reservados normalmente codificados en una sola byte (por ejemplo, el carácter nulo).
Además, algunos sistemas usan cadenas no restringidas: por ejemplo, Java (y otros lenguajes, incluidas las bibliotecas de manipulación de cadenas en C, PHP, Perl, etc.) representan caracteres con unidades de codificación en 16 bits (lo que hace posible almacenar cadenas usando UTF -16 codificación, pero sin las restricciones de validez impuestas por UTF-16 con respecto a valores prohibidos y emparejamiento en el orden de "semicódigos" o sustitutos ); en este caso, las unidades de codificación se tratan como valores binarios y es necesario serializarlas individualmente (independientemente de su posible interpretación como caracteres o como semipuntos de código). En este caso, cada unidad de codificación de 16 bits que representa un "carácter" (sin restricciones) se serializa en forma de secuencias que comprenden hasta 3 bytes cada una, y algunos bytes prohibidos por la implementación (por ejemplo, caracteres nulos o la barra de fracción ' / 'en un sistema de archivos u otros caracteres de un solo byte en otros protocolos) se codifican como secuencias de escape de doble byte, ninguna de las cuales es cero, simplemente usando el principio de codificación de la primera especificación de FSS-UTF (antes de la retenida por X / Open Consortium en su RFC inicial donde estas fugas estaban específicamente prohibidas y han permanecido así).
Antes de la adopción de la propuesta UTF-2 retenida para UTF-8, también existía una variante UTF-1, donde no era posible realizar múltiples codificaciones, pero requería una codificación / decodificación más difícil para tener en cuenta la posición de cada byte. una serie de valores "mágicos".
Estas variantes no deben llamarse "UTF-8".
Sin embargo, una de estas variantes no estándar fue objeto de una estandarización posterior (como alternativa a UTF-16 y utilizando pares de "medios códigos" cada uno codificado en 3 bytes; es decir, 6 bytes en total en lugar de 4 con UTF-8): ver CESU-8 .
Ejemplo de una variante utilizada en JavaPor ejemplo, las API de integración de máquinas virtuales Java (para JNI, Java Native Interface o para la serialización de clases precompiladas), que permiten el intercambio de cadenas Java sin restricciones en forma de secuencias de bytes (para manipularlas, usar o producir por código nativo, o para el almacenamiento como un archivo nativo codificado en cadenas de bytes), tienen el sufijo "UTFChars" o "UTF", pero esta codificación específica de Java no es UTF-8 (la documentación de Sun se refiere a ella como UTF modificado , pero algunos documentos JNI más antiguos todavía se refieren incorrectamente a esta codificación como UTF-8 , lo que ha producido algunas anomalías de comportamiento en algunas bibliotecas JNI nativas, especialmente con las API del sistema. Plataformas nativas más antiguas que no admiten de forma nativa codificaciones de caracteres de más de 8 bits ), porque:
En consecuencia :
Estos procesos pueden ser ineficientes para interconectar grandes cantidades de texto porque requieren la asignación de búferes de memoria adicionales para luego interactuar en código nativo con interfaces de red o de sistema que solo aceptan UTF-8 estándar.
Sin embargo, JNI también proporciona una API binaria más eficiente que permite usar UTF-16 directamente, capaz de interactuar directamente con protocolos de red e interfaces del sistema (por ejemplo, API de Windows) que admiten UTF-16, sin requerir ninguna asignación de memoria adicional para la transcodificación (solo la conformidad Puede ser necesario verificar, principalmente para verificar en el texto codificado el emparejamiento correcto del medio código o sustituto , que Java (como también otros lenguajes de programación) permite manipular sin restricción de validez en sus propias cadenas de caracteres no destinado a almacenar solo textos compatible con UCS). Esta API binaria es compatible con todos los sistemas en los que se ha portado Java, incluso aquellos cuyo sistema operativo no ofrece una API de texto Unicode (el soporte se puede realizar en la aplicación nativa del host o mediante el uso de las bibliotecas estándar suministradas con la JVM u otras bibliotecas nativas independientes). Bibliotecas.