UTF-8, UTF-16 y UTF-32

487

¿Cuáles son las diferencias entre UTF-8, UTF-16 y UTF-32?

Entiendo que todos almacenarán Unicode, y que cada uno usa un número diferente de bytes para representar un carácter. ¿Hay alguna ventaja en elegir uno sobre el otro?

Peter Mortensen
fuente
36
Mire este video si está interesado en cómo funciona Unicode youtube.com/watch?v=MijmeoH9LT4
1
El video se enfoca en UTF-8, y sí, explica bien cómo funciona la codificación de longitud variable y es principalmente compatible con computadoras que leen o escriben solo ASCII de longitud fija. Los chicos de Unicode fueron inteligentes al diseñar la codificación UTF-8.
minutos
1
He creado una herramienta en línea para la conversión y comparación.
Amit Kumar Gupta
1
UTF-8 es el estándar de facto en la mayoría del software moderno para archivos guardados . Más específicamente, es la codificación más utilizada para HTML y archivos de configuración y traducción (Minecraft, por ejemplo, no acepta ninguna otra codificación para toda su información de texto). UTF-32 es rápido para la representación de la memoria interna , y UTF-16 está en desuso , actualmente solo se usa en Win32 por razones históricas ( UTF-16 era de longitud fija cuando Windows 95 era una cosa)
Kotauskas
@VladislavToncharov UTF-16 nunca fue una codificación de longitud fija. Lo estás confundiendo con UCS-2.

Respuestas:

373

UTF-8 tiene una ventaja en el caso en que los caracteres ASCII representan la mayoría de los caracteres en un bloque de texto, porque UTF-8 los codifica en 8 bits (como ASCII). También es ventajoso porque un archivo UTF-8 que contiene solo caracteres ASCII tiene la misma codificación que un archivo ASCII.

UTF-16 es mejor donde ASCII no es predominante, ya que utiliza 2 bytes por carácter, principalmente. UTF-8 comenzará a usar 3 o más bytes para los caracteres de orden superior donde UTF-16 permanece en solo 2 bytes para la mayoría de los caracteres.

UTF-32 cubrirá todos los caracteres posibles en 4 bytes. Esto lo hace bastante hinchado. No se me ocurre ninguna ventaja al usarlo.

AnthonyWJones
fuente
165
Ventaja UTF-32: no necesita decodificar los datos almacenados en el punto de código Unicode de 32 bits para, por ejemplo, el manejo de caracteres por caracteres. El punto de código ya está disponible allí mismo en su matriz / vector / cadena.
richq
22
También es más fácil analizar si (el cielo te ayuda) tienes que volver a implementar la rueda.
Paul McMillan
24
Bueno, UTF-8 tiene una ventaja en las transferencias de red: no es necesario preocuparse por la resistencia, ya que está transfiriendo datos un byte a la vez (en lugar de 4).
Tim Čas
30
@richq No puede hacer el manejo de carácter por carácter en UTF-32, ya que el punto de código no siempre corresponde a un carácter.
Hamstergene
44
Ventaja UTF-32: la manipulación de cadenas es posiblemente más rápida en comparación con el equivalente utf-8
Wes
332

En breve:

  • UTF-8: codificación de ancho variable, compatible con ASCII. Los caracteres ASCII (U + 0000 a U + 007F) toman 1 byte, los puntos de código U + 0080 a U + 07FF toman 2 bytes, los puntos de código U + 0800 a U + FFFF toman 3 bytes, los puntos de código U + 10000 a U + 10FFFF tomar 4 bytes. Bueno para texto en inglés, no tan bueno para texto asiático.
  • UTF-16: codificación de ancho variable. Los puntos de código U + 0000 a U + FFFF toman 2 bytes, los puntos de código U + 10000 a U + 10FFFF toman 4 bytes. Malo para el texto en inglés, bueno para el texto asiático.
  • UTF-32: codificación de ancho fijo. Todos los puntos de código toman cuatro bytes. Un enorme cerdo de memoria, pero rápido para operar. Raramente usado.

En resumen: ver Wikipedia: UTF-8 , UTF-16 y UTF-32 .

Adam Rosenfield
fuente
65
@spurrymoses: me refiero estrictamente a la cantidad de espacio ocupado por los bytes de datos. UTF-8 requiere 3 bytes por carácter asiático, mientras que UTF-16 solo requiere 2 bytes por carácter asiático. Esto realmente no es un problema importante, ya que las computadoras tienen toneladas de memoria en estos días en comparación con la cantidad promedio de texto almacenado en la memoria de un programa.
Adam Rosenfield el
12
UTF-32 ya no se usa raramente ... en los valores wchar_tpredeterminados de osx y linux a 4 bytes. gcc tiene una opción -fshort-wcharque reduce el tamaño a 2 bytes, pero rompe la compatibilidad binaria con las bibliotecas estándar.
Vine'th
99
¡@PandaWood ofcource UTF-8 puede codificar cualquier personaje! ¿Pero ha comparado el requisito de memoria con el de UTF-16? ¡Usted parece estar perdiendo el punto!
Ustaman Sangat
16
Si alguien dijera que UTF-8 "no es tan bueno para el texto asiático" en el contexto de Todos los formatos de codificación, incluidos los que no pueden codificar Unicode, por supuesto estarían equivocados. Pero ese no es el contexto. El contexto de los requisitos de memoria proviene del hecho de que la pregunta (y la respuesta) está comparando UTF-8, UTF-16 y UTF-32, que codificarán texto asiático pero usarán diferentes cantidades de memoria / almacenamiento. De ello se deduce que su bondad relativa estaría naturalmente en el contexto de los requisitos de memoria. "No tan bueno"! = "No es bueno".
Paul Gregory
55
@McGafter: Bueno, por supuesto que sí. Si desea confiabilidad, vaya directamente a la boca del caballo en The Unicode Consortium . Consulte el capítulo 2.5 para obtener una descripción de las codificaciones UTF- *. Pero para obtener una comprensión simple y de alto nivel de las codificaciones, encuentro que los artículos de Wikipedia son una fuente mucho más accesible.
Adam Rosenfield
116
  • UTF-8 es variable de 1 a 4 bytes.

  • UTF-16 es variable 2 o 4 bytes.

  • UTF-32 tiene 4 bytes fijos .

Nota: UTF-8 puede tomar de 1 a 6 bytes con la última convención: https://lists.gnu.org/archive/html/help-flex/2005-01/msg00030.html

Quassnoi
fuente
35
UTF8 es en realidad de 1 a 6 bytes.
Urkle
66
@Urkle es técnicamente correcto porque el mapeo del rango completo de UTF32 / LE / BE incluye U-00200000 - U-7FFFFFFF aunque Unicode v6.3 termina en U-0010FFFF inclusive. Aquí hay un buen desglose de cómo enc / dec 5 y 6 bytes utf8: lists.gnu.org/archive/html/help-flex/2005-01/msg00030.html
44
respaldando estos con partes de referencias relevantes y sus fuentes?
n611x007
20
@Urkle No, UTF-8 no puede tener 5 o 6 bytes. Los puntos de código Unicode están limitados a 21 bits, lo que limita UTF-8 a 4 bytes. (Por supuesto, podría extender el principio de UTF-8 para codificar enteros grandes arbitrarios, pero no sería Unicode). Consulte RFC 3629.
rdb
11
Citando Wikipedia: en noviembre de 2003, UTF-8 fue restringido por RFC 3629 para coincidir con las restricciones de la codificación de caracteres UTF-16: prohibir explícitamente los puntos de código correspondientes a los caracteres sustitutos altos y bajos 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.
Adam Calvet Bohl el
79

Unicode define un único conjunto de caracteres enorme, asignando un valor entero único a cada símbolo gráfico (que es una simplificación importante, y no es realmente cierto, pero es lo suficientemente cerca para los fines de esta pregunta). UTF-8/16/32 son simplemente diferentes formas de codificar esto.

En resumen, UTF-32 usa valores de 32 bits para cada carácter. Eso les permite usar un código de ancho fijo para cada personaje.

UTF-16 usa 16 bits por defecto, pero eso solo le da 65k caracteres posibles, lo que no es lo suficientemente cercano para el conjunto completo de Unicode. Entonces, algunos caracteres usan pares de valores de 16 bits.

Y UTF-8 usa valores de 8 bits por defecto, lo que significa que los 127 primeros valores son caracteres de un byte de ancho fijo (el bit más significativo se usa para indicar que este es el comienzo de una secuencia de varios bytes, dejando 7 bits para el valor de carácter real). Todos los demás caracteres están codificados como secuencias de hasta 4 bytes (si la memoria sirve).

Y eso nos lleva a las ventajas. Cualquier carácter ASCII es directamente compatible con UTF-8, por lo que para actualizar aplicaciones heredadas, UTF-8 es una opción común y obvia. En casi todos los casos, también usará la menor cantidad de memoria. Por otro lado, no puedes hacer ninguna garantía sobre el ancho de un personaje. Puede tener 1, 2, 3 o 4 caracteres de ancho, lo que dificulta la manipulación de cadenas.

UTF-32 es opuesto, usa la mayor cantidad de memoria (cada carácter tiene un ancho fijo de 4 bytes), pero por otro lado, sabe que cada carácter tiene esta longitud precisa, por lo que la manipulación de cadenas se vuelve mucho más simple. Puede calcular el número de caracteres en una cadena simplemente a partir de la longitud en bytes de la cadena. No puedes hacer eso con UTF-8.

UTF-16 es un compromiso. Permite que la mayoría de los caracteres encajen en un valor de 16 bits de ancho fijo. Entonces, siempre que no tenga símbolos chinos, notas musicales u otros, puede suponer que cada carácter tiene 16 bits de ancho. Utiliza menos memoria que UTF-32. Pero de alguna manera es "lo peor de ambos mundos". Casi siempre usa más memoria que UTF-8, y todavía no evita el problema que afecta a UTF-8 (caracteres de longitud variable).

Finalmente, a menudo es útil ir con lo que la plataforma admite. Windows usa UTF-16 internamente, por lo que en Windows, esa es la opción obvia.

Linux varía un poco, pero generalmente usan UTF-8 para todo lo que es compatible con Unicode.

Respuesta breve: las tres codificaciones pueden codificar el mismo conjunto de caracteres, pero representan cada carácter como secuencias de bytes diferentes.

jalf
fuente
12
Es incorrecto decir que Unicode asigna un número entero único a cada símbolo gráfico . Asigna tal a cada punto de código, pero algunos puntos de código son caracteres de control invisibles , y algunos símbolos gráficos requieren múltiples puntos de código para representarlos.
tchrist
15
@tchrist: sí, es inexacto. El problema es que para explicar con precisión Unicode, debe escribir miles de páginas. Esperaba obtener el concepto básico para explicar la diferencia entre codificaciones
jalf
@jalf lol bien, así que básicamente para explicar Unicode tendrías que escribir la especificación básica de Unicode
Justin Ohms
@tchrist Más específicamente, puede construir símbolos chinos a partir de las primitivas proporcionadas (pero están en el mismo gráfico, por lo que terminará usando una cantidad de espacio irreal, ya sea disco o RAM, para codificarlos) en lugar de usar el los empotrados
Kotauskas
44

Unicode es un estándar y sobre UTF-x puede considerarse una implementación técnica para algunos fines prácticos:

  • UTF-8 - " tamaño optimizado ": más adecuado para datos basados ​​en caracteres latinos (o ASCII), solo toma 1 byte por carácter, pero el tamaño aumenta en consecuencia variedad de símbolos (y en el peor de los casos podría crecer hasta 6 bytes por carácter)
  • UTF-16 - " balance ": requiere un mínimo de 2 bytes por carácter, que es suficiente para el conjunto existente de idiomas principales con un tamaño fijo para facilitar el manejo de caracteres (pero el tamaño sigue siendo variable y puede crecer hasta 4 bytes por carácter )
  • UTF-32 - " rendimiento ": permite el uso de algoritmos simples como resultado de caracteres de tamaño fijo (4 bytes) pero con desventaja de memoria
torre
fuente
«Idiomas principales» no es la corriente principal en muchas partes del mundo ^^
tuxayo
2
UTF-16 es en realidad tamaño optimizado para caracteres no ASCII. Porque realmente depende de qué idiomas se usará.
tuxayo
@tuxayo está totalmente de acuerdo, vale la pena señalar conjuntos de caracteres Hanzi y Kanji para la parte asiática del mundo.
torre
Debería ser la mejor respuesta. Esto es demasiado correcto para ser enterrado aquí.
Michal Štein
28

Traté de dar una explicación simple en mi blog .

UTF-32

requiere 32 bits (4 bytes) para codificar cualquier carácter. Por ejemplo, para representar el punto de código de carácter "A" utilizando este esquema, deberá escribir 65 en un número binario de 32 bits:

00000000 00000000 00000000 01000001 (Big Endian)

Si observa más de cerca, notará que los siete bits más correctos son en realidad los mismos bits cuando se utiliza el esquema ASCII. Pero como UTF-32 es un esquema de ancho fijo , debemos adjuntar tres bytes adicionales. Lo que significa que si tenemos dos archivos que solo contienen el carácter "A", uno está codificado en ASCII y el otro está codificado en UTF-32, su tamaño será de 1 byte y 4 bytes correspondientes.

UTF-16

Mucha gente piensa que como UTF-32 usa un ancho fijo de 32 bits para representar un punto de código, UTF-16 es un ancho fijo de 16 bits. ¡INCORRECTO!

En UTF-16, el punto de código puede representarse en 16 bits o en 32 bits. Entonces, este esquema es un sistema de codificación de longitud variable. ¿Cuál es la ventaja sobre el UTF-32? Al menos para ASCII, el tamaño de los archivos no será 4 veces el original (pero aún dos veces), por lo que todavía no somos ASCII compatibles con versiones anteriores.

Dado que 7 bits son suficientes para representar el carácter "A", ahora podemos usar 2 bytes en lugar de 4 como el UTF-32. Se verá así:

00000000 01000001

UTF-8

Has acertado. En UTF-8, el punto de código puede representarse utilizando 32, 16, 24 u 8 bits, y como el sistema UTF-16, este también es un sistema de codificación de longitud variable.

Finalmente podemos representar "A" de la misma manera que lo representamos usando el sistema de codificación ASCII:

01001101

Un pequeño ejemplo donde UTF-16 es realmente mejor que UTF-8:

Considere la letra china "語": su codificación UTF-8 es:

11101000 10101010 10011110

Si bien su codificación UTF-16 es más corta:

10001010 10011110

Para comprender la representación y cómo se interpreta, visite la publicación original.

Maroun
fuente
19

UTF-8

  • no tiene concepto de orden de bytes
  • utiliza entre 1 y 4 bytes por carácter
  • ASCII es un subconjunto compatible de codificación
  • completamente auto-sincronizado, por ejemplo, un byte descartado desde cualquier parte de una secuencia corromperá como máximo un solo carácter
  • Casi todos los idiomas europeos están codificados en dos bytes o menos por carácter

UTF-16

  • debe analizarse con un orden de bytes conocido o leer una marca de orden de bytes (BOM)
  • usa 2 o 4 bytes por carácter

UTF-32

  • cada caracter tiene 4 bytes
  • debe analizarse con un orden de bytes conocido o leer una marca de orden de bytes (BOM)

UTF-8 será el espacio más eficiente a menos que la mayoría de los caracteres sean del espacio de caracteres CJK (chino, japonés y coreano).

UTF-32 es mejor para acceso aleatorio por desplazamiento de caracteres en una matriz de bytes.

Jeff Adamson
fuente
¿Cómo funciona la "sincronización automática" en UTF-8? ¿Puedes dar ejemplos de caracteres de 1 byte y 2 byte?
Koray Tugay
2
@KorayTugay Las cadenas de bytes más cortas válidas nunca se usan en caracteres más largos. Por ejemplo, ASCII está en el rango de 0-127, lo que significa que todos los caracteres de un byte tienen la forma 0xxxxxxxen binario. Todos los caracteres de dos bytes comienzan 110xxxxxcon un segundo byte de 10xxxxxx. Entonces, digamos que se pierde el primer carácter de un carácter de dos bytes. Tan pronto como vea 10xxxxxxsin un precedente 110xxxxxx, puede determinar con certeza si un byte se perdió o corrompió, y descarte ese carácter (o vuelva a solicitarlo de un servidor o lo que sea), y continúe hasta que vea un primer byte válido nuevamente .
Chris
1
si tiene el desplazamiento de un carácter, tiene el desplazamiento de ese carácter: utf8, utf16 o utf32 funcionarán igual en ese caso; es decir, todos son igualmente buenos en acceso aleatorio por desplazamiento de caracteres en una matriz de bytes. La idea de que utf32 es mejor para contar caracteres que utf8 también es completamente falsa. Un punto de código (que no es lo mismo que un carácter que, de nuevo, no es lo mismo que un grafema ... suspiro), tiene 32 bits de ancho en utf32 y entre 8 y 32 bits en utf8, pero un carácter puede abarcar múltiples puntos de código, que destruye la gran ventaja que la gente dice que utf32 tiene sobre utf8.
Más claro
14

Hice algunas pruebas para comparar el rendimiento de la base de datos entre UTF-8 y UTF-16 en MySQL.

Actualizar velocidades

UTF-8

Ingrese la descripción de la imagen aquí

UTF-16

Ingrese la descripción de la imagen aquí

Insertar velocidades

Ingrese la descripción de la imagen aquí

Ingrese la descripción de la imagen aquí

Eliminar velocidades

Ingrese la descripción de la imagen aquí

Ingrese la descripción de la imagen aquí

Farid Movsumov
fuente
14

En UTF-32, todos los caracteres están codificados con 32 bits. La ventaja es que puede calcular fácilmente la longitud de la cadena. La desventaja es que por cada carácter ASCII desperdicia tres bytes adicionales.

En los caracteres UTF-8 tienen una longitud variable, los caracteres ASCII se codifican en un byte (ocho bits), la mayoría de los caracteres especiales occidentales se codifican en dos bytes o tres bytes (por ejemplo, € es tres bytes), y pueden tomar más caracteres exóticos a cuatro bytes. La clara desventaja es que a priori no se puede calcular la longitud de la cadena. Pero se necesitan muchos menos bytes para codificar el texto del alfabeto latino (inglés), en comparación con UTF-32.

UTF-16 también es de longitud variable. Los caracteres se codifican en dos bytes o cuatro bytes. Realmente no veo el punto. Tiene la desventaja de ser de longitud variable, pero no tiene la ventaja de ahorrar tanto espacio como UTF-8.

De esos tres, claramente UTF-8 es el más extendido.

vartec
fuente
¿Por qué querría calcular la longitud de la cadena mientras desarrollo sitios web? ¿Hay alguna ventaja de elegir UTF-8 / UTF-16 en el desarrollo web?
Morfidon
"La ventaja es que puede calcular fácilmente la longitud de la cadena" Si define la longitud por el número de puntos de código, entonces sí, puede dividir la longitud del byte entre 4 para obtenerla con UTF-32. Sin embargo, esa no es una definición muy útil: puede no estar relacionada con la cantidad de caracteres. Además, la normalización puede alterar el número de puntos de código en la cadena. Por ejemplo, la palabra francesa "été" se puede codificar en al menos 4 formas diferentes, con 3 longitudes de puntos de código distintas.
UTF-16 es posiblemente más rápido que UTF-8 mientras que tampoco desperdicia memoria como lo hace UTF-32.
Michal Štein
6

Según su entorno de desarrollo, es posible que ni siquiera tenga la opción de elegir qué codificación usará internamente su tipo de datos de cadena.

Pero para almacenar e intercambiar datos, siempre usaría UTF-8, si tiene la opción. Si tiene datos ASCII en su mayoría, esto le dará la menor cantidad de datos para transferir, al tiempo que podrá codificar todo. La optimización para el mínimo de E / S es el camino a seguir en las máquinas modernas.

mghie
fuente
Podría decirse que mucho más importante que los requisitos de espacio es el hecho de que UTF-8 es inmune a la resistencia. UTF-16 y UTF-32 inevitablemente tendrán que lidiar con problemas de endianness, donde UTF-8 es simplemente una corriente de octetos.
Inspeccionable el
2

Como se mencionó, la diferencia es principalmente el tamaño de las variables subyacentes, que en cada caso se hacen más grandes para permitir que se representen más caracteres.

Sin embargo, las fuentes, la codificación y las cosas son terriblemente complicadas (¿innecesariamente?), Por lo que se necesita un gran enlace para completar más detalles:

http://www.cs.tut.fi/~jkorpela/chars.html#ascii

No esperes entenderlo todo, pero si no quieres tener problemas más tarde, vale la pena aprender tanto como puedas, tan pronto como puedas (o simplemente conseguir que alguien más lo resuelva por ti).

Pablo.

Paul W Homer
fuente
o simplemente use UTF-8 por defecto, ya que se ha convertido en el estándar de facto, y descubra si un nuevo sistema lo admite o no. si no es así, puedes volver a esta publicación.
robotik
-2

En resumen, la única razón para usar UTF-16 o UTF-32 es para admitir scripts antiguos y no ingleses respectivamente.

Me preguntaba por qué alguien elegiría tener una codificación que no sea UTF-8 cuando obviamente es más eficiente para fines web / de programación.

Un error común: el número con sufijo NO es una indicación de su capacidad. Todos son compatibles con Unicode completo, solo que UTF-8 puede manejar ASCII con un solo byte, por lo que es MÁS eficiente / menos corruptible para la CPU y para Internet.

Algunas buenas lecturas: http://www.personal.psu.edu/ejp10/blogs/gotunicode/2007/10/which_utf_do_i_use.html y http://utf8everywhere.org

aguafiestas
fuente
No estoy seguro, por qué sugiere, que el uso de UTF-16 o UTF-32 sea compatible con texto que no esté en inglés. UTF-8 puede manejar eso muy bien. Y también hay caracteres que no son ASCII en el texto en inglés. Como un no-carpintero de ancho cero. O un em dash. Me temo que esta respuesta no agrega mucho valor.
Inspeccionable el
Esta pregunta es susceptible de voto negativo porque UTF-8 todavía se usa comúnmente en archivos HTML, incluso si la mayoría de los caracteres son caracteres de 3 bytes en UTF-8,
Ṃųỻịgǻňạcểơửṩ
El soporte de @IInspectable no es la mejor redacción, promover o un mejor soporte sería más preciso
robotik
Enviar una página como utf8everywhere.org no es lo que haría en una respuesta SO.
Michal Štein