UTF-8
UTF-8 es una codificación de caracteres de longitud variable utilizada para la comunicación electrónica. Definido por el estándar Unicode, el nombre se deriva de Unicode (o Conjunto de caracteres codificados universales) Formato de transformación: 8 bits.
UTF-8 es capaz de codificar los 1 112 064 puntos de código de caracteres válidos en Unicode utilizando de una a cuatro unidades de código de un byte (8 bits). Los puntos de código con valores numéricos más bajos, que tienden a ocurrir con mayor frecuencia, se codifican con menos bytes. Fue diseñado para compatibilidad con versiones anteriores de ASCII: los primeros 128 caracteres de Unicode, que se corresponden uno a uno con ASCII, se codifican utilizando un solo byte con el mismo valor binario que ASCII, de modo que el texto ASCII válido es UTF-8 válido Unicode codificado también.
UTF-8 se diseñó como una alternativa superior a UTF-1, una codificación de longitud variable propuesta con compatibilidad parcial con ASCII que carecía de algunas funciones, como la sincronización automática y el manejo totalmente compatible con ASCII de caracteres como barras oblicuas. Ken Thompson y Rob Pike produjeron la primera implementación del sistema operativo Plan 9 en septiembre de 1992. Esto llevó a que X/Open lo adoptara como su especificación para FSS-UTF, que se presentaría oficialmente por primera vez en USENIX en enero de 1993 y posteriormente adoptado por el Grupo de Trabajo de Ingeniería de Internet (IETF) en RFC 2277 (BCP 18) para el futuro de Internet los estándares funcionan, reemplazando los conjuntos de caracteres de un solo byte como Latin-1 en los RFC más antiguos.
UTF-8 es la codificación dominante para la World Wide Web (y las tecnologías de Internet), y representa el 98,0% de todas las páginas web y hasta el 100,0% para muchos idiomas, a partir de 2022.
Nombramiento
El código oficial de la Autoridad de Números Asignados en Internet (IANA) para la codificación es "UTF-8". Todas las letras están en mayúsculas y el nombre está separado por guiones. Esta ortografía se usa en todos los documentos del Consorcio Unicode relacionados con la codificación. Sin embargo, el nombre "utf-8" puede ser utilizado por todos los estándares que se ajustan a la lista IANA (que incluyen encabezados CSS, HTML, XML y HTTP), ya que la declaración no distingue entre mayúsculas y minúsculas.
Otras variantes, como las que omiten el guión o lo reemplazan por un espacio, es decir, "utf8" o "UTF 8", no son aceptados como correctos por los estándares vigentes. A pesar de esto, la mayoría de los navegadores web pueden entenderlos, por lo que los estándares destinados a describir la práctica existente (como HTML5) pueden requerir efectivamente su reconocimiento.
"UTF-8-BOM" y "UTF-8-NOBOM" a veces se usan para archivos de texto que contienen o no contienen una marca de orden de bytes (BOM), respectivamente. Especialmente en Japón, la codificación UTF-8 sin BOM a veces se denomina "UTF-8N".
En Windows, UTF-8 es la página de códigos 65001 (es decir, CP_UTF8
en el código fuente).
En HP PCL, UTF-8 se denomina Id. de símbolo "18N".
Codificación
UTF-8 codifica puntos de código en uno a cuatro bytes, según el valor del punto de código. Los caracteres x se reemplazan por los bits del punto de código:
Primer punto de código | Último punto de código | Byte 1 | Byte 2 | Byte 3 | Byte 4 | Puntos de código |
---|---|---|---|---|---|---|
U+0000 | U+007F | 0xxxxxxxx | 128 | |||
U+0080 | U+07FF | 110xxxxxx | 10xxxxxxx | 1920 | ||
U+0800 | U+FF | 1110xxxx | 10xxxxxxx | 10xxxxxxx | 61440 | |
U+10000 | U+10FF | 11110xxx | 10xxxxxxx | 10xxxxxxx | 10xxxxxxx | 1048576 |
Los primeros 128 puntos de código (ASCII) necesitan un byte. Los siguientes 1920 puntos de código necesitan dos bytes para codificarse, lo que cubre el resto de casi todos los alfabetos latinos, y también las extensiones IPA, los alfabetos griego, cirílico, copto, armenio, hebreo, árabe, siríaco, thaana y n'ko., así como la combinación de marcas diacríticas. Se necesitan tres bytes para el resto del plano multilingüe básico, que contiene prácticamente todos los puntos de código de uso común, incluidos la mayoría de los caracteres chinos, japoneses y coreanos. Se necesitan cuatro bytes para puntos de código en los otros planos de Unicode, que incluyen caracteres CJK menos comunes, varias escrituras históricas, símbolos matemáticos y emoji (símbolos pictográficos).
Un "personaje" puede tomar más de 4 bytes porque está hecho de más de un punto de código. Por ejemplo, un carácter de bandera nacional ocupa 8 bytes ya que está 'construido a partir de un par de valores escalares Unicode'. ambos desde fuera del BMP.
Ejemplos
Considere la codificación del símbolo del euro, €:
- El punto de código Unicode para € es U+20AC.
- Como este punto de código está entre U+0800 y U+FFFF, esto tomará tres bytes para codificar.
- Hexadecimal 20AC es binario 0010 0000 1010 1100. Los dos ceros principales se añaden porque una codificación de tres bytes necesita exactamente dieciséis bits desde el punto de código.
- Debido a que la codificación será de tres bytes de largo, su byte líder comienza con tres 1s, luego un 0 (1110...)
- Los cuatro bits más significativos del punto de código se almacenan en el orden bajo restante cuatro bits de este byte (11100010), dejando 12 bits del punto de código aún por ser codificado (...0000 1010 1100).
- Todos los bytes de continuación contienen exactamente seis bits del punto de código. Así que los próximos seis bits del punto de código se almacenan en el orden bajo seis bits del siguiente byte, y 10 se almacena en el orden alto dos bits para marcarlo como un byte de continuación (so 10000010).
- Finalmente los últimos seis bits del punto de código se almacenan en el orden bajo seis bits del byte final, y de nuevo 10 se almacena en el orden alto dos bits (10101100).
Los tres bytes 11100010 10000010 10101100 se puede escribir de manera más concisa en hexadecimal, como E2 82 CA.
La siguiente tabla resume esta conversión, así como otras con diferentes longitudes en UTF-8. Los colores indican cómo se distribuyen los bits del punto de código entre los bytes UTF-8. Los bits adicionales agregados por el proceso de codificación UTF-8 se muestran en negro.
Cara | Punto de código binario | Binary UTF-8 | Hex UTF-8 | |
---|---|---|---|---|
$ | U+0024 | 010 0100 | 00100 | 24 |
£ | U+00A3 | 00010 0011 | 11000010 10100011 | C2 A3 |
. | U+0939 | 0000 1001 0011 1001 | 11100000 10100100 10111001 | E0 A4 B9 |
€ | U+20AC | 0010 0000 1010 1100 | 11100010 10000010 10101100 | E2 82 AC |
한 | U+D55C | 1101 0101 0101 1100 | 11101101 10010101 10011100 | ED 95 9C |
𐍈 | U+10348 | 0 0001 0000 0011 0100 | 11110000 10010000 10001101 10001000 | F0 90 8D 88 |
Octubre
El uso de UTF-8 de seis bits por byte para representar los caracteres reales que se codifican significa que la notación octal (que usa grupos de 3 bits) puede ayudar en la comparación de secuencias UTF-8 entre sí y en conversión manual.
Primer punto de código | Último punto de código | Punto de código | Byte 1 | Byte 2 | Byte 3 | Byte 4 |
---|---|---|---|---|---|---|
000 | 0177 | xxxx | xxxx | |||
0200 | 03777 | xxyy | 3xx | 2y | ||
04000 | 077777 | xyzz | 34x | 2y | 2zz | |
0100000 | 0177777 | 1xyzz | 35x | 2y | 2zz | |
0200000 | 04177777 | xyzzw | 36x | 2y | 2zz | 2ww |
Con la notación octal, los dígitos octales arbitrarios, marcados con x, y, z o w en la tabla, permanecerán sin cambios al convertir a o desde UTF-8.
- Ejemplo: Á = U+00C1 = 0301 (en octal) se codifica como 303 201 en UTF-8 (C3 81 en hex).
- Ejemplo: € = U+20AC = 020254 está codificado como 342 202 254 en UTF-8 (E2 82 AC en hex).
Diseño de página de códigos
La siguiente tabla resume el uso de unidades de código UTF-8 (bytes u octetos individuales) en un formato de página de código. La mitad superior es para bytes que se usan solo en códigos de un solo byte, por lo que parece una página de códigos normal; la mitad inferior es para bytes de continuación y bytes iniciales y se explica con más detalle en la leyenda a continuación.
UTF-8 | ||||||||||||||||
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F | |
0x | NUL | SOH | STX | ETX | EOT | ENQ | ACK | BEL | BS | HT | LF | VT | FF | CR | SO | SI |
1x | DLE | DC1 | DC2 | DC3 | DC4 | NAK | SYN | ETB | CAN | EM | SUB | ESC | SM | SG | RS | EE.UU. |
2x | SP | ! | " | # | $ | % | " | ' | () | ) | * | + | , | - | . | / |
3x | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | : | ; | . | = | ■ | ? |
4x | @ | A | B | C | D | E | F | G | H | I | J | K | L | M | N | O |
5x | P | Q | R | S | T | U | V | W | X | Y | Z | [ | ] | ^ | ¿Qué? | |
6x | ` | a | b | c | d | e | f | g | h | i | j | k | l | m | n | o |
7x | p | q | r | s | t | u | v | w | x | Sí. | z | {} | Silencio | } | ~ | DEL |
8x | • | • | • | • | • | • | • | • | • | • | • | • | • | • | • | • |
9x | • | • | • | • | • | • | • | • | • | • | • | • | • | • | • | • |
Ax | • | • | • | • | • | • | • | • | • | • | • | • | • | • | • | • |
Bx | • | • | • | • | • | • | • | • | • | • | • | • | • | • | • | • |
Cx | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 2 |
Dx | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 2 | 2 |
Ex | 3 | 3 | 3 | 3 | 3 | 3 | 3 | 3 | 3 | 3 | 3 | 3 | 3 | 3 | 3 | 3 |
Fx | 4 | 4 | 4 | 4 | 4 | 4 | 4 | 4 | 5 | 5 | 5 | 5 | 6 | 6 | ||
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F |
Codificaciones demasiado largas
En principio, sería posible inflar el número de bytes en una codificación rellenando el punto de código con ceros iniciales. Para codificar el símbolo del euro € del ejemplo anterior en cuatro bytes en lugar de tres, podría rellenarse con ceros iniciales hasta que tuviera 21 bits de largo: 000 000010 000010 101100, y codificado como 11110000 10000010 10000010 10101100 (o F0 82 82 AC en hexadecimal). Esto se denomina codificación demasiado larga.
El estándar especifica que la codificación correcta de un punto de código utiliza solo la cantidad mínima de bytes necesarios para contener los bits significativos del punto de código. Las codificaciones más largas se denominan overlong y no son representaciones UTF-8 válidas del punto de código. Esta regla mantiene una correspondencia uno a uno entre los puntos de código y sus codificaciones válidas, de modo que existe una codificación válida única para cada punto de código. Esto garantiza que las comparaciones y búsquedas de cadenas estén bien definidas.
Secuencias no válidas y manejo de errores
No todas las secuencias de bytes son UTF-8 válidas. Un decodificador UTF-8 debe estar preparado para:
- portes inválidos
- un inesperado byte de continuación
- un byte no continuo antes del final del personaje
- la cuerda que termina antes del final del personaje (que puede suceder en simple truncación de cuerda)
- una codificación excesiva
- una secuencia que decodifica a un punto de código inválido
Muchos de los primeros decodificadores UTF-8 los decodificaban, ignorando los bits incorrectos y aceptando resultados demasiado largos. El UTF-8 no válido cuidadosamente diseñado podría hacer que se salten o creen caracteres ASCII como NUL, barra inclinada o comillas. Se ha utilizado UTF-8 no válido para eludir las validaciones de seguridad en productos de alto perfil, incluido el servidor web IIS de Microsoft y el contenedor de servlet Tomcat de Apache. RFC 3629 establece "Las implementaciones del algoritmo de decodificación DEBEN proteger contra la decodificación de secuencias no válidas." El estándar Unicode requiere que los decodificadores "... traten cualquier secuencia de unidades de código mal formadas como una condición de error. Esto garantiza que no interpretará ni emitirá una secuencia de unidades de código mal formada."
Desde RFC 3629 (noviembre de 2003), las mitades sustitutas alta y baja utilizadas por UTF-16 (U+D800 a U+DFFF) y los puntos de código no codificables por UTF-16 (aquellos después de U+10FFFF) no son legales Los valores Unicode y su codificación UTF-8 deben tratarse como una secuencia de bytes no válida. No descodificar mitades sustitutas no emparejadas hace que sea imposible almacenar UTF-16 no válido (como nombres de archivo de Windows o UTF-16 que se ha dividido entre los suplentes) como UTF-8, mientras que es posible con WTF-8.
Algunas implementaciones de decodificadores lanzan excepciones en errores. Esto tiene la desventaja de que puede convertir lo que de otro modo serían errores inofensivos (como un error 'no existe tal archivo') en una denegación de servicio. Por ejemplo, las primeras versiones de Python 3.0 saldrían inmediatamente si la línea de comando o las variables de entorno contenían UTF-8 no válido. Una práctica alternativa es reemplazar los errores con un carácter de reemplazo. Desde Unicode 6 (octubre de 2010), el estándar (capítulo 3) ha recomendado una "mejor práctica" donde el error termina tan pronto como se encuentra un byte no permitido. En estos decodificadores E1,A0,C0 hay dos errores (2 bytes en el primero). Esto significa que un error no tiene más de tres bytes y nunca contiene el comienzo de un carácter válido, y hay 21,952 errores posibles diferentes. El estándar también recomienda reemplazar cada error con el carácter de reemplazo "�" (U+FFFD).
Marca de orden de bytes
Si el carácter de marca de orden de bytes Unicode (BOM, U+FEFF) está al comienzo de un archivo UTF-8, los primeros tres bytes serán 0xEF, 0xBB, 0xBF.
El estándar Unicode no requiere ni recomienda el uso de BOM para UTF-8, pero advierte que se puede encontrar al comienzo de un archivo transcodificado desde otra codificación. Si bien el texto ASCII codificado con UTF-8 es compatible con versiones anteriores de ASCII, esto no es cierto cuando se ignoran las recomendaciones del estándar Unicode y se agrega una lista de materiales. Una lista de materiales puede confundir el software que no está preparado para ello, pero que puede aceptar UTF-8, p. lenguajes de programación que permiten bytes que no son ASCII en cadenas literales pero no al comienzo del archivo. Sin embargo, hubo y todavía hay software que siempre inserta una lista de materiales al escribir UTF-8 y se niega a interpretar correctamente UTF-8 a menos que el primer carácter sea una lista de materiales (o el archivo solo contiene ASCII).
Adopción
Muchos estándares solo admiten UTF-8, p. el intercambio JSON abierto lo requiere (sin una marca de orden de bytes (BOM)). UTF-8 también es la recomendación de WHATWG para las especificaciones de HTML y DOM, y el Consorcio de correo de Internet recomienda que todos los programas de correo electrónico puedan mostrar y crear correo usando UTF-8. El Consorcio World Wide Web recomienda UTF-8 como la codificación predeterminada en XML y HTML (y no solo usar UTF-8, también declararlo en los metadatos), "incluso cuando todos los caracteres están en el rango ASCII... Usando las codificaciones que no son UTF-8 pueden tener resultados inesperados.
Mucho software tiene la capacidad de leer/escribir UTF-8 y, para algunas funciones, UTF-8 es la única opción. Sin embargo, en algunos casos, puede requerir que el usuario cambie las opciones de la configuración normal, o puede requerir una BOM (marca de orden de bytes) como el primer carácter para leer el archivo. Los ejemplos de software compatibles con UTF-8 incluyen Google Drive y LibreOffice, la mayoría de las bases de datos admiten UTF-8.
UTF-8 ha sido la codificación más común para la World Wide Web desde 2008. En noviembre de 2022, UTF-8 representa una media del 98,0 % de todas las páginas web (y 990 de las 1000 páginas web mejor clasificadas).. Aunque muchas páginas solo usan caracteres ASCII para mostrar contenido, pocos sitios web ahora declaran que su codificación es solo ASCII en lugar de UTF-8. Más de un tercio de los idiomas rastreados tienen un uso del 100 % de UTF-8.
Para los archivos de texto locales, el uso de UTF-8 es menos frecuente, donde algunas codificaciones heredadas de un solo byte (y algunas CJK de varios bytes) permanecen en uso hasta cierto punto. La causa principal de esto son algunos editores de texto que se niegan a usar UTF-8 al procesar archivos, a menos que los primeros bytes del archivo codifiquen un carácter de marca de orden de bytes (BOM). Sin embargo, como la mayoría de los editores de texto correctamente no requieren una lista de materiales, a menudo no insertan una lista de materiales al principio de los archivos que guardan, lo que provoca problemas de compatibilidad con dichos editores. Para admitir editores que esperan una lista de materiales, se debe agregar una lista de materiales manualmente al inicio del archivo. Muchos otros editores de texto simplemente asumen una codificación UTF-8 para todos los archivos debido a su casi omnipresencia. A partir de Windows 10, el Bloc de notas de Windows escribe de forma predeterminada UTF-8 sin una lista de materiales (un cambio desde Windows 7), lo que lo pone en línea con la mayoría de los demás editores de texto. Con respecto a los archivos del sistema, algunos archivos del sistema en Windows 11 requieren UTF-8 sin necesidad de una BOM, y casi todos los archivos en macOS y Linux deben ser UTF-8 sin una BOM. Por defecto, Java 18 lee y escribe archivos como UTF-8 y, en versiones anteriores (por ejemplo, versiones LTS), solo se cambió la API de NIO para hacerlo. Muchos otros lenguajes de programación utilizan de forma predeterminada UTF-8 para E/S, incluidos Ruby 3.0 y R 4.2.2. Todas las versiones compatibles actualmente de Python admiten UTF-8 para E/S, incluso en Windows (donde está habilitado para la función open()
), y existen planes para hacer UTF-8 I/O. O el predeterminado en Python 3.15 en todas las plataformas.
El uso de UTF-8 dentro del software también es menor que en otras áreas, ya que a menudo se usa UTF-16 en su lugar. Esto ocurre particularmente en Windows, pero también en JavaScript, Python, Qt y muchas otras bibliotecas de software multiplataforma. La compatibilidad con la API de Windows es la razón principal de esto, aunque la creencia de que la indexación directa de BMP mejora la velocidad también fue un factor. El software más reciente ha comenzado a usar UTF-8 casi exclusivamente: la primitiva de cadena predeterminada en Go, Julia, Rust, Swift 5 y PyPy usa UTF-8; se planea una versión futura de Python para almacenar cadenas como UTF-8; y las versiones modernas de Microsoft Visual Studio usan UTF-8 internamente (aunque aún requieren un interruptor de línea de comandos para leer o escribir UTF-8). UTF-8 es la "única codificación de texto que debe admitir el estándar C++" en C++20. Todas las versiones de Windows compatibles actualmente admiten UTF-8 de alguna manera (incluida Xbox); existe soporte parcial desde al menos Windows XP. A partir de mayo de 2019, Microsoft cambió su posición anterior de solo recomendar UTF-16; se introdujo la capacidad de establecer UTF-8 como codificación para la API de Windows. A partir de 2020, Microsoft recomienda que los programadores usen UTF-8.
Historia
La Organización Internacional para la Estandarización (ISO) se propuso componer un juego de caracteres multibyte universal en 1989. El borrador del estándar ISO 10646 contenía un anexo no requerido llamado UTF-1 que proporcionaba una codificación de flujo de bytes de su 32- puntos de código de bits. Esta codificación no era satisfactoria por motivos de rendimiento, entre otros problemas, y el mayor problema probablemente era que no tenía una separación clara entre ASCII y no ASCII: las nuevas herramientas UTF-1 serían compatibles con versiones anteriores del texto codificado en ASCII, pero El texto codificado en UTF-1 podría confundir el código existente que espera ASCII (o ASCII extendido), porque podría contener bytes de continuación en el rango 0x21–0x7E que significaba algo más en ASCII, por ejemplo, 0x2F para '/', el separador de directorios de ruta de Unix, y este ejemplo se refleja en el nombre y el texto introductorio de su reemplazo. La siguiente tabla se derivó de una descripción textual en el anexo.
Número de bytes | Primera punto | Último punto | Byte 1 | Byte 2 | Byte 3 | Byte 4 | Byte 5 |
---|---|---|---|---|---|---|---|
1 | U+0000 | U+009F | 00 a 9F | ||||
2 | U+00A0 | U+00FF | A0 | A0-FF | |||
2 | U+0100 | U+4015 | A1–F5 | 21–7E, A0–FF | |||
3 | U+4016 | U+38E2D | F6-FB | 21–7E, A0–FF | 21–7E, A0–FF | ||
5 | U+38E2E | U+7FFFF | FC-FF | 21–7E, A0–FF | 21–7E, A0–FF | 21–7E, A0–FF | 21–7E, A0–FF |
En julio de 1992, el comité X/Open XoJIG buscaba una mejor codificación. Dave Prosser de Unix System Laboratories presentó una propuesta que tenía características de implementación más rápidas e introdujo la mejora de que los caracteres ASCII de 7 bits solo se representarían a sí mismos; todas las secuencias de varios bytes incluirían solo los bytes donde se estableció el bit alto. El nombre File System Safe UCS Transformation Format (FSS-UTF) y la mayor parte del texto de esta propuesta se conservaron posteriormente en la especificación final.
FSS-UTF
Número de bytes | Primera punto | Último punto | Byte 1 | Byte 2 | Byte 3 | Byte 4 | Byte 5 |
---|---|---|---|---|---|---|---|
1 | U+0000 | U+007F | 0xxxxxxxx | ||||
2 | U+0080 | U+207F | 10xxxxxxx | 1xxxxxxxx | |||
3 | U+2080 | U+8207F | 110xxxxxx | 1xxxxxxxx | 1xxxxxxxx | ||
4 | U+82080 | U+208207F | 1110xxxx | 1xxxxxxxx | 1xxxxxxxx | 1xxxxxxxx | |
5 | U+2082080 | U+7FFFF | 11110xxx | 1xxxxxxxx | 1xxxxxxxx | 1xxxxxxxx | 1xxxxxxxx |
En agosto de 1992, un representante de IBM X/Open hizo circular esta propuesta entre las partes interesadas. Una modificación realizada por Ken Thompson del grupo del sistema operativo Plan 9 en Bell Labs hizo que se sincronice automáticamente, lo que permite que un lector comience en cualquier lugar e inmediatamente detecte los límites de los caracteres, a costa de ser algo menos eficiente que la propuesta anterior. También abandonó el uso de sesgos y, en cambio, agregó la regla de que solo se permite la codificación más corta posible; la pérdida adicional de compacidad es relativamente insignificante, pero los lectores ahora deben buscar codificaciones no válidas para evitar problemas de confiabilidad y especialmente de seguridad. El diseño de Thompson se esbozó el 2 de septiembre de 1992 en un mantel individual en un restaurante de Nueva Jersey con Rob Pike. En los días siguientes, Pike y Thompson lo implementaron y actualizaron Plan 9 para usarlo en todo momento, y luego comunicaron su éxito a X/Open, que lo aceptó como la especificación para FSS-UTF.
Número de bytes | Primera punto | Último punto | Byte 1 | Byte 2 | Byte 3 | Byte 4 | Byte 5 | Byte 6 |
---|---|---|---|---|---|---|---|---|
1 | U+0000 | U+007F | 0xxxxxxxx | |||||
2 | U+0080 | U+07FF | 110xxxxxx | 10xxxxxxx | ||||
3 | U+0800 | U+FF | 1110xxxx | 10xxxxxxx | 10xxxxxxx | |||
4 | U+10000 | U+1FFF | 11110xxx | 10xxxxxxx | 10xxxxxxx | 10xxxxxxx | ||
5 | U+200000 | U+3FFFF | 111110xx | 10xxxxxxx | 10xxxxxxx | 10xxxxxxx | 10xxxxxxx | |
6 | U+4000000 | U+7FFFF | 1111110x | 10xxxxxxx | 10xxxxxxx | 10xxxxxxx | 10xxxxxxx | 10xxxxxxx |
UTF-8 se presentó oficialmente por primera vez en la conferencia USENIX en San Diego, del 25 al 29 de enero de 1993. El Grupo de Trabajo de Ingeniería de Internet adoptó UTF-8 en su Política sobre conjuntos de caracteres e idiomas en RFC 2277 (BCP 18) para el futuro trabajo de los estándares de Internet, reemplazando los conjuntos de caracteres de un solo byte como Latin-1 en los RFC más antiguos.
En noviembre de 2003, RFC 3629 restringió UTF-8 para que coincidiera con las restricciones de la codificación de caracteres UTF-16: al prohibir explícitamente los puntos de código correspondientes a los caracteres sustitutos alto y bajo, se eliminó más del 3% de las secuencias de tres bytes., y terminando en U+10FFFF eliminó más del 48 % de las secuencias de cuatro bytes y todas las secuencias de cinco y seis bytes.
Estándares
Hay varias definiciones actuales de UTF-8 en varios documentos de estándares:
- RFC 3629 / STD 63 (2003), que establece UTF-8 como elemento protocolo estándar de Internet
- RFC 5198 define UTF-8 NFC for Network Interchange (2008)
- ISO/IEC 10646:2014 §9.1 (2014)
- El estándar Unicode, versión 14.0.0 (2021)
Reemplazan las definiciones dadas en los siguientes trabajos obsoletos:
- El estándar Unicode, versión 2.0, Apéndice A (1996)
- ISO/IEC 10646-1:1993 Enmienda 2 / Anexo R (1996)
- RFC 2044 (1996)
- RFC 2279 (1998)
- El estándar Unicode, versión 3.0, §2.3 (2000) plus Corrigendum #1: UTF-8 Shortest Form (2000)
- Unicode Standard Annex #27: Unicode 3.1 (2001)
- El estándar Unicode, versión 5.0 (2006)
- El estándar Unicode, versión 6.0 (2010)
Todos son iguales en su mecánica general, con las principales diferencias en cuestiones como el rango permitido de valores de puntos de código y el manejo seguro de entradas no válidas.
Comparación con otras codificaciones
Algunas de las características importantes de esta codificación son las siguientes:
- Compatibilidad trasera: La compatibilidad con ASCII y la enorme cantidad de software diseñado para procesar el texto codificado por ASCII fue la principal fuerza motriz detrás del diseño de UTF-8. En UTF-8, bytes individuales con valores en el rango de 0 a 127 mapa directamente a puntos de código Unicode en el rango ASCII. Los bytes individuales en esta gama representan caracteres, como lo hacen en ASCII. Además, los bytes de 7 bits (bytes donde el bit más significativo es 0) nunca aparecen en una secuencia de varios bytes, y ninguna secuencia válida de varios bytes decodifica a un código ASCII. Una secuencia de bytes de 7 bits es válida ASCII y válida UTF-8, y bajo cualquier interpretación representa la misma secuencia de caracteres. Por lo tanto, los bytes de 7 bits en un flujo UTF-8 representan todos y sólo los caracteres ASCII en el flujo. Por lo tanto, muchos procesadores de texto, analizadores, protocolos, formatos de archivo, programas de visualización de texto, etc., que utilizan caracteres ASCII para los propósitos de formato y control, continuarán trabajando como se pretendía tratar el flujo de byte UTF-8 como una secuencia de caracteres de un byte, sin decodificar las secuencias de varios bytes. Los caracteres ASCII en los que el procesamiento gira, como punción, espacio blanco y caracteres de control nunca serán codificados como secuencias de varios bytes. Por lo tanto, es seguro para estos procesadores simplemente ignorar o pasar por las secuencias de varios bytes, sin decodificarlos. Por ejemplo, el espacio blanco ASCII puede usarse para registrar una corriente UTF-8 en palabras; las semillas de línea ASCII pueden utilizarse para dividir una corriente UTF-8 en líneas; y los caracteres NUL ASCII pueden ser utilizados para dividir los datos codificados UTF-8 en cadenas nulas. Del mismo modo, muchas cadenas de formato utilizadas por funciones de biblioteca como "printf" manejarán correctamente los argumentos de entrada codificados por UTF-8.
- Fallback y auto-detección: Sólo un pequeño subconjunto de cadenas posibles de byte es una cadena UTF-8 válida: no pueden aparecer varios bytes; un byte con el conjunto de bits elevados no puede estar solo; y otros requisitos significan que es extremadamente improbable que un texto legible en cualquier ASCII ampliado sea válido UTF-8. Parte de la popularidad de UTF-8 se debe a que proporciona una forma de compatibilidad atrasada para estos también. Un procesador UTF-8 que recibe erróneamente ASCII extendido como entrada puede así "auto-detect" esto con muy alta fiabilidad. Un flujo UTF-8 puede simplemente contener errores, lo que resulta en el esquema de auto-detección produciendo falsos positivos; pero la auto-detección es exitosa en la gran mayoría de los casos, especialmente con textos más largos, y es ampliamente utilizado. También funciona para "caer" o sustituir los bytes de 8 bits utilizando el punto de código apropiado para una codificación heredada cuando se detectan errores en la UTF-8, permitiendo la recuperación incluso si UTF-8 y la codificación heredada se concaten en el mismo archivo.
- Código prefijo: El primer byte indica el número de bytes en la secuencia. La lectura de un flujo puede descifrar instantáneamente cada individuo completamente recibido secuencia, sin tener que esperar primero el primer byte de una siguiente secuencia o una indicación final de corriente. La longitud de las secuencias de varios bytes es fácilmente determinada por los humanos, ya que es simplemente el número de 1s de alto orden en el byte principal. Un personaje incorrecto no será decodificado si un flujo termina a mitad de la secuencia.
- Autosincronización: Los bytes líderes y los bytes de continuación no comparten valores (los bytes de continuidad comienzan con los bits 10 mientras los bytes individuales comienzan con 0 y los bytes más largos comienzan con 11). Esto significa que una búsqueda no encontrará accidentalmente la secuencia de un personaje que comienza en medio de otro personaje. También significa que el comienzo de un personaje se puede encontrar desde una posición aleatoria respaldando a la mayoría de 3 bytes para encontrar el byte principal. Un personaje incorrecto no será decodificado si un flujo comienza a media secuencia, y una secuencia más corta nunca aparecerá dentro de uno más largo.
- Orden de clasificación: Los valores elegidos de los bytes principales significan que una lista de cadenas UTF-8 se pueden clasificar en orden de punto de código clasificando las secuencias de byte correspondientes.
Byte único
- UTF-8 puede codificar cualquier personaje Unicode, evitando la necesidad de averiguar y establecer una "página de código" o de otro modo indicar qué carácter está en uso, y permitiendo la salida en múltiples scripts al mismo tiempo. Para muchos scripts ha habido más de una codificación de un solo byte en el uso, por lo que incluso sabiendo que el script era información insuficiente para mostrarlo correctamente.
- Los bytes 0xFE y 0xFF no aparecen, por lo que un flujo UTF-8 válido nunca coincide con la marca de orden UTF-16 byte y por lo tanto no puede confundirse con ella. La ausencia de 0xFF (0377) también elimina la necesidad de escapar de este byte en Telnet (y la conexión de control FTP).
- El texto codificado UTF-8 es más grande que los códigos especializados de un solo byte excepto para caracteres ASCII simples. En el caso de scripts que utilizaron conjuntos de caracteres de 8 bits con caracteres no latinos codificados en la mitad superior (como la mayoría de las páginas de códigos de alfabeto cirílico y griego), los caracteres en UTF-8 serán dobles del tamaño. Para algunos scripts, como Thai y Devanagari (que es utilizado por varios idiomas del sur de Asia), los caracteres se triplicarán en tamaño. Incluso hay ejemplos en los que un solo byte se convierte en un personaje compuesto en Unicode y por lo tanto es seis veces mayor en UTF-8. Esto ha causado objeciones en la India y en otros países.
- Es posible en UTF-8 (o cualquier otra codificación multibyte) dividir o truncar una cadena en medio de un personaje. Si las dos piezas no se vuelven a aplicar más adelante antes de la interpretación como caracteres, esto puede introducir una secuencia inválida tanto al final de la sección anterior como al comienzo de la siguiente, y algunos decodificadores no conservarán estos bytes y resultarán en la pérdida de datos. Debido a que UTF-8 está autosincronizando esto sin embargo nunca introducirá un carácter válido diferente, y también es bastante fácil mover el punto de truncación hacia atrás al comienzo de un personaje.
- Si los puntos de código son del mismo tamaño, las mediciones de un número fijo de ellos es fácil. Debido a la documentación de la era ASCII donde el "caracter" se utiliza como sinónimo de "byte" esto se considera a menudo importante. Sin embargo, midiendo posiciones de cadena usando bytes en lugar de "characters" la mayoría de algoritmos pueden ser fácilmente y eficientemente adaptados para UTF-8. Buscar una cadena dentro de una cadena larga puede por ejemplo ser hecho byte; la propiedad de la autosincronización evita falsos positivos.
Otros multibyte
- UTF-8 puede codificar cualquier personaje Unicode. Los archivos en diferentes scripts se pueden mostrar correctamente sin tener que elegir la página de código o fuente correcta. Por ejemplo, chino y árabe se puede escribir en el mismo archivo sin marcación especializada o configuración manual que especifique una codificación.
- UTF-8 es autosincronización: los límites de caracteres se identifican fácilmente escaneando patrones de bit bien definidos en cualquier dirección. Si los bytes se pierden debido al error o la corrupción, siempre se puede localizar el siguiente carácter válido y reanudar el procesamiento. Si hay una necesidad de acortar una cadena para encajar en un campo especificado, el carácter válido anterior se puede encontrar fácilmente. Muchos encodings multibytes como Shift JIS son mucho más difíciles de sincronizar. Esto también significa que los algoritmos de búsqueda de cuerdas orientados por byte se pueden utilizar con UTF-8 (como un personaje es el mismo que una "palabra" compuesta por muchos bytes), las versiones optimizadas de búsquedas byte pueden ser mucho más rápidas debido a soporte de hardware y tablas de búsqueda que tienen sólo 256 entradas. Sin embargo, la autosincronización requiere que los bits estén reservados para estos marcadores en cada byte, aumentando el tamaño.
- Eficiente para codificar usando operaciones simples bitwise. UTF-8 no requiere operaciones matemáticas más lentas como la multiplicación o división (a diferencia de Shift JIS, GB 2312 y otras codificación).
- UTF-8 tomará más espacio que una codificación multibyte diseñada para un script específico. Las codificaciones heredadas de Asia oriental generalmente utilizan dos bytes por personaje, pero toman tres bytes por personaje en UTF-8.
UTF-16
- Los encodings Byte y UTF-8 están representados por arrays byte en programas, y a menudo nada necesita ser hecho a una función al convertir el código fuente de una codificación byte a UTF-8. UTF-16 está representado por arrays de palabras de 16 bits, y la conversión a UTF-16 manteniendo la compatibilidad con los programas existentes basados en ASCII (como se hizo con Windows) requiere cada uno API y estructura de datos que requiere duplicar una cadena, una versión aceptando cadenas byte y otra versión aceptando UTF-16. Si la compatibilidad atrasada no es necesaria, todo el manejo de cuerdas todavía debe ser modificado.
- El texto codificado en UTF-8 será más pequeño que el mismo texto codificado en UTF-16 si hay más puntos de código debajo de U+0080 que en el rango U+0800.. U+FF. Esto es cierto para todos los idiomas europeos modernos. A menudo es cierto incluso para idiomas como chino, debido al gran número de espacios, nuevas líneas, dígitos y marcado HTML en archivos típicos.
- La mayor parte de la comunicación (por ejemplo, HTML e IP) y el almacenamiento (por ejemplo, para Unix) fue diseñado para un flujo de bytes. Una cadena UTF-16 debe usar un par de bytes para cada unidad de código:
- El orden de esos dos bytes se convierte en un problema y debe especificarse en el protocolo UTF-16, como con una marca de orden de byte.
- Si extraño número de bytes falta de UTF-16, todo el resto de la cadena será texto sin sentido. Los bytes que faltan de UTF-8 todavía permitirán que el texto sea recuperado con precisión comenzando con el siguiente personaje después de los bytes desaparecidos.
Derivados
Las siguientes implementaciones muestran ligeras diferencias con respecto a la especificación UTF-8. Son incompatibles con la especificación UTF-8 y pueden ser rechazados por aplicaciones UTF-8 conformes.
CESU-8
El informe técnico n.° 26 de Unicode asigna el nombre CESU-8 a una variante no estándar de UTF-8, en la que los caracteres Unicode en planos complementarios se codifican con seis bytes, en lugar de los cuatro bytes requeridos por UTF-8. La codificación CESU-8 trata cada mitad de un par sustituto UTF-16 de cuatro bytes como un carácter UCS-2 de dos bytes, lo que produce dos caracteres UTF-8 de tres bytes, que juntos representan el carácter complementario original. Los caracteres Unicode dentro del plano multilingüe básico aparecen como lo harían normalmente en UTF-8. El Informe se escribió para reconocer y formalizar la existencia de datos codificados como CESU-8, a pesar de que el Consorcio Unicode desaconseja su uso, y señala que una posible razón intencional para la codificación CESU-8 es la preservación de la intercalación binaria UTF-16.
La codificación CESU-8 puede resultar de la conversión de datos UTF-16 con caracteres complementarios a UTF-8, utilizando métodos de conversión que asumen datos UCS-2, lo que significa que no conocen los caracteres complementarios UTF-16 de cuatro bytes. Se trata principalmente de un problema en los sistemas operativos que utilizan UTF-16 de forma interna, como Microsoft Windows.
En Oracle Database, el conjunto de caracteres UTF8
utiliza la codificación CESU-8 y está en desuso. El conjunto de caracteres AL32UTF8
utiliza UTF-8 compatible con los estándares codificación, y se prefiere.
CESU-8 está prohibido para su uso en documentos HTML5.
MySQL utf8mb3
En MySQL, el juego de caracteres utf8mb3
es definido como datos codificados en UTF-8 con un máximo de tres bytes por carácter, lo que significa que solo se admiten caracteres Unicode en el plano multilingüe básico (es decir, de UCS-2). Los caracteres Unicode en planos suplementarios no se admiten explícitamente. utf8mb3
está en desuso en favor de utf8mb4
conjunto de caracteres, que utiliza la codificación UTF-8 compatible con los estándares. utf8
es un alias para utf8mb3
, pero pretende convertirse en un alias para utf8mb4
en una versión futura de MySQL. Es posible, aunque no compatible, almacenar datos codificados CESU-8 en utf8mb3
, manejando datos UTF-16 con caracteres adicionales como si fueran UCS-2.
UTF-8 modificada
(feminine)UTF-8 modificado (MUTF-8) se originó en el lenguaje de programación Java. En UTF-8 modificado, el carácter nulo (U+0000) usa la codificación demasiado larga de dos bytes 11000000 10000000 (hexadecimal C0 80), en lugar de 00000000 (hexadecimal 00). Las cadenas UTF-8 modificadas nunca contienen bytes nulos reales, pero pueden contener todos los puntos de código Unicode, incluido U+0000, lo que permite que dichas cadenas (con un byte nulo adjunto) sean procesadas por funciones tradicionales de cadenas terminadas en nulo. Todas las implementaciones conocidas de UTF-8 modificado también tratan los pares sustitutos como en CESU-8.
En uso normal, el lenguaje admite UTF-8 estándar al leer y escribir cadenas a través de InputStreamReader
y OutputStreamWriter
(si es el conjunto de caracteres predeterminado de la plataforma o según lo solicite el programa). Sin embargo, utiliza UTF-8 modificado para la serialización de objetos entre otras aplicaciones de DataInput
y DataOutput
, para la interfaz nativa de Java y para incrustar cadenas constantes en archivos de clase.
El formato dex definido por Dalvik también usa el mismo UTF-8 modificado para representar valores de cadena. Tcl también usa el mismo UTF-8 modificado que Java para la representación interna de datos Unicode, pero usa CESU-8 estricto para datos externos.
WTF-8
En WTF-8 (formato de transformación tambaleante, 8 bits) se permiten mitades sustitutas sin emparejar (U+D800 a U+DFFF). Esto es necesario para almacenar UTF-16 posiblemente no válido, como los nombres de archivo de Windows. Muchos sistemas que manejan UTF-8 funcionan de esta manera sin considerarlo una codificación diferente, ya que es más simple.
(El término "WTF-8" también se ha usado con humor para referirse a UTF-8 doblemente codificado erróneamente a veces con la implicación de que los bytes CP1252 son los únicos codificados).
PEP 383
La versión 3 del lenguaje de programación Python trata cada byte de un flujo de bytes UTF-8 no válido como un error (consulte también los cambios con el nuevo modo UTF-8 en Python 3.7); esto da 128 posibles errores diferentes. Se han creado extensiones para permitir que cualquier secuencia de bytes que se suponga que es UTF-8 se transforme sin pérdidas a UTF-16 o UTF-32, traduciendo los 128 bytes de error posibles a puntos de código reservados y transformando esos puntos de código nuevamente en error. bytes para generar UTF-8. El enfoque más común es traducir los códigos a U+DC80...U+DCFF, que son valores sustitutos bajos (de seguimiento) y, por lo tanto, "inválidos" UTF-16, como se usa en el enfoque PEP 383 (o "surrogateescape") de Python. Otra codificación llamada MirBSD OPTU-8/16 los convierte a U+EF80...U+EFFF en un Área de Uso Privado. En cualquier enfoque, el valor del byte se codifica en los ocho bits inferiores del punto de código de salida.
Estas codificaciones son muy útiles porque evitan la necesidad de tratar con "no válido" cadenas de bytes hasta mucho más tarde, en todo caso, y permitir "texto" y "datos" matrices de bytes para ser el mismo objeto. Si un programa quiere usar UTF-16 internamente, estos son necesarios para preservar y usar nombres de archivo que pueden usar UTF-8 no válido; como la API del sistema de archivos de Windows usa UTF-16, la necesidad de admitir UTF-8 no válido es menor allí.
Para que la codificación sea reversible, las codificaciones UTF-8 estándar de los puntos de código utilizados para los bytes erróneos deben considerarse no válidas. Esto hace que la codificación sea incompatible con WTF-8 o CESU-8 (aunque solo para 128 puntos de código). Al volver a codificar, es necesario tener cuidado con las secuencias de puntos de código de error que se vuelven a convertir a UTF-8 válido, que puede ser utilizado por software malicioso para obtener caracteres inesperados en la salida, aunque esto no puede producir caracteres ASCII, por lo que se considera comparativamente seguro, ya que las secuencias maliciosas (como las secuencias de comandos entre sitios) generalmente se basan en caracteres ASCII.
Contenido relacionado
Acordeón
Formato de número de computadora
Aviación general