¿Cuántos bytes tiene un carácter Unicode?

239

Estoy un poco confundido acerca de las codificaciones. Hasta donde yo sé, los caracteres ASCII antiguos tomaban un byte por carácter. ¿Cuántos bytes requiere un carácter Unicode?

Supongo que un carácter Unicode puede contener todos los caracteres posibles de cualquier idioma. ¿Estoy en lo correcto? Entonces, ¿cuántos bytes necesita por carácter?

¿Y qué significan UTF-7, UTF-6, UTF-16, etc.? ¿Son diferentes versiones de Unicode?

Leí el artículo de Wikipedia sobre Unicode pero es bastante difícil para mí. Tengo muchas ganas de ver una respuesta simple.

yaya
fuente
15
Lo sentimos, no hay una respuesta simple. Todo esto me parece un desastre. Se facturó a Unicode por usar dos bytes y poder representar todos los caracteres, pero resulta que dos bytes no fueron suficientes.
Jonathan Wood
12
"Respuesta simple": un carácter unicode toma 1-4 bytes. Unicode cubre muchos idiomas pero no todos. La última vez que miré, por ejemplo, Klingon no era un juego de caracteres oficial de Unicode.
Peter G.
99
Klingon no es parte del estándar Unicode en sí, no. En su lugar, utiliza el Área de uso privado de Uniode (U + F8D0 - U + F8FF).
Remy Lebeau
1
Pregunta del salvador: gracias. Mi situación es almacenar datos a través de LMS compatibles con SCORM 1.2 ... el estándar para 'cmi.suspend_data' de SCORM 1.2 es 4096 bytes de datos que un desarrollador anterior supuso significaba que podíamos almacenar 4096 caracteres. Oh hombre, estaba equivocado: acabo de descubrir por qué nuestro marcador falla en cursos largos. Así que ahora sé que estamos usando UTF-8, se necesitan 4 bytes por carácter, lo que nos da 1024 caracteres.
danjah

Respuestas:

147

No verá una respuesta simple porque no hay una.

Primero, Unicode no contiene "todos los caracteres de cada idioma", aunque sí lo intenta.

Unicode en sí es un mapeo, define puntos de código y un punto de código es un número, asociado generalmente con un carácter. Digo generalmente porque hay conceptos como combinar personajes. Puede estar familiarizado con cosas como acentos o diéresis. Esos se pueden usar con otro personaje, como un ao a upara crear un nuevo personaje lógico. Por lo tanto, un personaje puede constar de 1 o más puntos de código.

Para ser útiles en los sistemas informáticos, debemos elegir una representación para esta información. Esas son las diversas codificaciones Unicode, como utf-8, utf-16le, utf-32, etc. Se distinguen en gran medida por el tamaño de sus unidades de código. UTF-32 es la codificación más simple, tiene una unidad de código de 32 bits, lo que significa que un punto de código individual se adapta cómodamente a una unidad de código. Las otras codificaciones tendrán situaciones en las que un punto de código necesitará múltiples unidades de código, o ese punto de código particular no se puede representar en la codificación (esto es un problema, por ejemplo, con UCS-2).

Debido a la flexibilidad de combinar caracteres, incluso dentro de una codificación dada, el número de bytes por carácter puede variar según el carácter y la forma de normalización. Este es un protocolo para tratar con caracteres que tienen más de una representación (puede decir "an 'a' with an accent"cuál es 2 puntos de código, uno de los cuales es un carácter de combinación o "accented 'a'"cuál es un punto de código).

Logan Capaldo
fuente
1
OKAY. Entonces, ¿cuántos bytes toma un carácter dado representado en un punto de código dado? Por ejemplo, el espacio sin ruptura.
Nicolas Barbulesco
Los caracteres combinados hacen que la vida de un programador sea un infierno cuando se trata de escribir strlen (), substr () y otras funciones de manipulación de cadenas en matrices UTF8. Este tipo de trabajo nunca será completo y siempre tendrá errores.
Nulik
Escribí una demostración que muestra los archivos codificados de Windows-1252, UTF8 y UTF8-BOM interpretados con cada codificación, y compara la igualdad entre los resultados: github.com/vladyrn/encodings_demo
Vlad
195

Por extraño que parezca, nadie señaló cómo calcular cuántos bytes está tomando un carácter Unicode. Aquí está la regla para las cadenas codificadas UTF-8:

Binary    Hex          Comments
0xxxxxxx  0x00..0x7F   Only byte of a 1-byte character encoding
10xxxxxx  0x80..0xBF   Continuation byte: one of 1-3 bytes following the first
110xxxxx  0xC0..0xDF   First byte of a 2-byte character encoding
1110xxxx  0xE0..0xEF   First byte of a 3-byte character encoding
11110xxx  0xF0..0xF7   First byte of a 4-byte character encoding

Entonces, la respuesta rápida es: toma de 1 a 4 bytes, dependiendo del primero, que indicará cuántos bytes ocupará.

paul.ago
fuente
8
Creo que el valor máximo de Hex para un carácter de 4 bytes es 0xF7 (no 0xF4).
DJPJ
Muchas gracias! Solo estaba controlando + f'ing a través del estándar IETF, y no encontré nada sobre la codificación, y el artículo que estaba leyendo no entró en detalles suficientes para decir cuántos bits se utilizan para representar la cantidad de código final puntos por "personaje".
MarcusJ
1
Esto está ahora en la segunda página de mi hoja de trucos "Introducción para los nuevos miembros del equipo", junto con los dos primeros comentarios hilarantes
Cee McSharpface
1
0xF4 no fue un error sino una aclaración. Los puntos de código Unicode están en el rango 0-0x10ffff, por lo que el último punto de código se codifica como F4 8F BF BF.
Frediano Ziglio
38

Sé que esta pregunta es antigua y ya tiene una respuesta aceptada, pero quiero ofrecer algunos ejemplos (con la esperanza de que sea útil para alguien).

Hasta donde yo sé, los caracteres ASCII antiguos tomaban un byte por carácter.

Correcto. En realidad, dado que ASCII es una codificación de 7 bits, admite 128 códigos (95 de los cuales son imprimibles), por lo que solo usa medio byte (si eso tiene sentido).

¿Cuántos bytes requiere un carácter Unicode?

Unicode solo asigna caracteres a puntos de código. No define cómo codificarlos. Un archivo de texto no contiene caracteres Unicode, sino bytes / octetos que pueden representar caracteres Unicode.

Supongo que un carácter Unicode puede contener todos los caracteres posibles de cualquier idioma. ¿Estoy en lo correcto?

No. Pero casi. Entonces básicamente sí. Pero aun así no.

Entonces, ¿cuántos bytes necesita por carácter?

Igual que su segunda pregunta.

¿Y qué significan UTF-7, UTF-6, UTF-16, etc.? ¿Son algunas versiones amables de Unicode?

No, esas son codificaciones. Definen cómo los bytes / octetos deben representar caracteres Unicode.

Un par de ejemplos Si algunos de ellos no se pueden mostrar en su navegador (probablemente porque la fuente no los admite), vaya a http://codepoints.net/U+1F6AA(reemplazar 1F6AAcon el punto de código en hexadecimal) para ver una imagen.

    • U + 0061 LETRA LATINA PEQUEÑA A: a
      • Nº: 97
      • UTF-8: 61
      • UTF-16: 00 61
    • U + 00A9 SIGNO DE DERECHOS DE AUTOR: ©
      • Nº: 169
      • UTF-8: C2 A9
      • UTF-16: 00 A9
    • U + 00AE FIRMA REGISTRADA: ®
      • Nº: 174
      • UTF-8: C2 AE
      • UTF-16: 00 AE
    • U + 1337 PHWA SÍLABLE ETIÓPICO:
      • Nº: 4919
      • UTF-8: E1 8C B7
      • UTF-16: 13 37
    • U + 2014 EM DASH:
      • Nº: 8212
      • UTF-8: E2 80 94
      • UTF-16: 20 14
    • U + 2030 POR SEÑAL POR MILLA:
      • Nº: 8240
      • UTF-8: E2 80 B0
      • UTF-16: 20 30
    • U + 20AC SIGNO EURO:
      • Nº: 8364
      • UTF-8: E2 82 AC
      • UTF-16: 20 AC
    • Signo de marca comercial U + 2122:
      • Nº: 8482
      • UTF-8: E2 84 A2
      • UTF-16: 21 22
    • U + 2603 SNOWMAN:
      • Nº: 9731
      • UTF-8: E2 98 83
      • UTF-16: 26 03
    • TELÉFONO NEGRO U + 260E:
      • Nº: 9742
      • UTF-8: E2 98 8E
      • UTF-16: 26 0E
    • PARAGUAS U + 2614 CON GOTAS DE LLUVIA:
      • Nº: 9748
      • UTF-8: E2 98 94
      • UTF-16: 26 14
    • U + 263A CARA SONRIENTE BLANCA:
      • Nº: 9786
      • UTF-8: E2 98 BA
      • UTF-16: 26 3A
    • U + 2691 BANDERA NEGRA:
      • Nº: 9873
      • UTF-8: E2 9A 91
      • UTF-16: 26 91
    • SÍMBOLO DE ÁTOMO U + 269B:
      • Nº: 9883
      • UTF-8: E2 9A 9B
      • UTF-16: 26 9B
    • AEROPUERTO U + 2708:
      • Nº: 9992
      • UTF-8: E2 9C 88
      • UTF-16: 27 08
    • CRUZ LATINA BLANCA SOMBRADA U + 271E:
      • Nº: 10014
      • UTF-8: E2 9C 9E
      • UTF-16: 27 1E
    • U + 3020 CARA POSTAL MARCA:
      • Nº: 12320
      • UTF-8: E3 80 A0
      • UTF-16: 30 20
    • U + 8089 CJK IDEOGRAFO UNIFICADO-8089:
      • Nº: 32905
      • UTF-8: E8 82 89
      • UTF-16: 80 89
    • U + 1F4A9 PILA DE POO: 💩
      • Nº: 128169
      • UTF-8: F0 9F 92 A9
      • UTF-16: D8 3D DC A9
    • U + 1F680 ROCKET: 🚀
      • Nº: 128640
      • UTF-8: F0 9F 9A 80
      • UTF-16: D8 3D DE 80

Ok, me estoy dejando llevar ...

Hechos graciosos:

básico6
fuente
Las unidades de código en UTF-16 tienen 16 bits de ancho. Les mostraste con un espacio en el medio, lo cual es engañoso. La representación UTF-16 para © debería ser en 00A9lugar de 00 A9(que sería UTF-16BE).
Roland Illig
¿Cual es la diferencia? ¿No significa SER endian grande? Lo escribió en big endian, por lo que un archivo escrito en big endian UTF-16 sería el mismo que UTF-16BE, ¿verdad?
HappyPandaFace
66
Correcciones: 1) ASCII tiene 7 bits, un byte tiene 8 bits, por lo que es mucho más de la mitad. 2) Unicode define cómo codificar los puntos de código. UTF-8, UTF-16 y UTF-32 se definen en el estándar Unicode.
Jonathan Rosenne
3
@JonathanRosenne Creo que quería decir que solo usa la mitad de los valores posibles representables con 8 bits, no que usa la mitad de los bits.
Aritz Lopez
2
Realmente me gustan los ejemplos. Destacan por qué uno puede preferir UTF-16 sobre UTF-8, por ejemplo. Los desarrolladores de diferentes programas pueden seleccionar diferentes codificaciones en función de las cuales es más probable que se usen los caracteres Unicode. En China / Japón, por ejemplo, UTF-16 (2 bytes) tiene más sentido que UTF-8 para ellos, porque los mismos caracteres a menudo necesitarían el doble de bytes para codificar en UTF-8
Mike
29

Simplemente hablando Unicodees un estándar que asigna un número (llamado punto de código) a todos los personajes del mundo (todavía está en progreso).

Ahora necesita representar estos puntos de código usando bytes, eso se llama character encoding. UTF-8, UTF-16, UTF-6son formas de representar a esos personajes.

UTF-8es codificación de caracteres multibyte. Los caracteres pueden tener de 1 a 6 bytes (algunos de ellos pueden no ser necesarios en este momento).

UTF-32 cada caracter tiene 4 bytes por caracter.

UTF-16usa 16 bits para cada carácter y representa solo una parte de los caracteres Unicode llamados BMP (para todos los fines prácticos es suficiente). Java usa esta codificación en sus cadenas.

Zimbabao
fuente
10
Unicode es un conjunto de códigos de 21 bits y 4 bytes son suficientes para representar cualquier carácter Unicode en UTF-8. UTF-16 usa sustitutos para representar caracteres fuera del BMP (plano multilingüe básico); necesita 2 o 4 bytes para representar cualquier carácter Unicode válido. UCS-2 era la única variante de 16 bits de UTF-16 sin soporte para sustitutos o personajes fuera del BMP.
Jonathan Leffler
1
Estás en lo correcto. El UTF-8 original tenía 6 bytes para acomodar un bit de 32. En realidad no quería complicar mucho las cosas, ya que él ya estaba confundido con wiki doc :)
Zimbabao
3
Esta respuesta indica que UTF-16 no puede codificar puntos de código BMP. Esto es incorrecto, ya que pueden codificarse de la misma manera que en UTF-8 utilizando pares sustitutos. (Debe estar pensando en el UCS-2 desactualizado, antes de que saliera Unicode 2.0, que codificaba solo puntos de código de 16 bits). Además, Java no usa UTF-16, usa una forma modificada del mismo donde el punto de código 0 está codificado de manera diferente.
rdb
@rdb: es todo lo contrario. La respuesta dice que UTF-16 representa el BMP.
Nicolas Barbulesco
3
Me equivoqué; Tenía la intención de decir "no BMP". El error en la respuesta es que dice que UTF-16 representa caracteres BMP, lo cual es inexacto. UTF-16 puede codificar todos los caracteres unicode: los caracteres que no son BMP se codifican a través de pares sustitutos. Quizás el respondedor fue confundido con UCS-2.
rdb
17

En UTF-8:

1 byte:       0 -     7F     (ASCII)
2 bytes:     80 -    7FF     (all European plus some Middle Eastern)
3 bytes:    800 -   FFFF     (multilingual plane incl. the top 1792 and private-use)
4 bytes:  10000 - 10FFFF

En UTF-16:

2 bytes:      0 -   D7FF     (multilingual plane except the top 1792 and private-use )
4 bytes:   D800 - 10FFFF

En UTF-32:

4 bytes:      0 - 10FFFF

10FFFF es el último punto de código Unicode por definición, y se define de esa manera porque es el límite técnico de UTF-16.

También es el punto de código más grande que UTF-8 puede codificar en 4 bytes, pero la idea detrás de la codificación de UTF-8 también funciona para codificaciones de 5 y 6 bytes para cubrir puntos de código hasta 7FFFFFFF, es decir. la mitad de lo que puede UTF-32.

Juan
fuente
8

En Unicode, la respuesta no se da fácilmente. El problema, como ya señaló, son las codificaciones.

Dada cualquier oración en inglés sin caracteres diacríticos, la respuesta para UTF-8 sería tantos bytes como caracteres y para UTF-16 sería el número de caracteres multiplicado por dos.

La única codificación donde (a partir de ahora) podemos hacer la declaración sobre el tamaño es UTF-32. Siempre hay 32 bits por carácter, aunque imagino que los puntos de código están preparados para un futuro UTF-64 :)

Lo que lo hace tan difícil son al menos dos cosas:

  1. caracteres compuestos, donde en lugar de utilizar la entidad de caracteres que ya está acentuada / diacrítica (À), un usuario decidió combinar el acento y el carácter base (`A).
  2. puntos de código Los puntos de código son el método por el cual las codificaciones UTF permiten codificar más del número de bits que generalmente les permite su nombre. Por ejemplo, UTF-8 designa ciertos bytes que por sí solos no son válidos, pero cuando es seguido por un byte de continuación válido permitirá describir un carácter más allá del rango de 8 bits de 0..255. Ver los ejemplos y codificaciones excesivas a continuación en el artículo de Wikipedia sobre UTF-8.
    • La excelente ejemplo dado no es que el personaje € (punto de código U+20ACse puede representar ya sea como de tres bytes de secuencia E2 82 ACo cuatro bytes de secuencia F0 82 82 AC.
    • Ambos son válidos, y esto muestra cuán complicada es la respuesta cuando se habla de "Unicode" y no de una codificación específica de Unicode, como UTF-8 o UTF-16.
0xC0000022L
fuente
4

Bueno, también abrí la página de Wikipedia, y en la parte de introducción vi "Unicode puede implementarse mediante diferentes codificaciones de caracteres. Las codificaciones más utilizadas son UTF-8 (que usa un byte para cualquier carácter ASCII, que tiene los mismos valores de código en la codificación UTF-8 y ASCII, y hasta cuatro bytes para otros caracteres), el UCS-2 ahora obsoleto (que usa dos bytes para cada carácter pero no puede codificar cada carácter en el estándar Unicode actual) "

Como lo demuestra esta cita, su problema es que está asumiendo que Unicode es una forma única de codificar caracteres. En realidad, hay varias formas de Unicode, y, de nuevo en esa cita, una de ellas incluso tiene 1 byte por carácter, al igual que a lo que estás acostumbrado.

Entonces, su respuesta simple que desea es que varía.

Loduwijk
fuente
3

Para UTF-16, el carácter necesita cuatro bytes (dos unidades de código) si comienza con 0xD800 o superior; dicho personaje se llama "par sustituto". Más específicamente, un par sustituto tiene la forma:

[0xD800 - 0xDBFF]  [0xDC00 - 0xDFF]

donde [...] indica una unidad de código de dos bytes con el rango dado. Cualquier cosa <= 0xD7FF es una unidad de código (dos bytes). Cualquier cosa> = 0xE000 no es válida (excepto los marcadores de lista de materiales, posiblemente).

Consulte http://unicodebook.readthedocs.io/unicode_encodings.html , sección 7.5.

prewett
fuente
1

De Wiki:

UTF-8, una codificación de ancho variable de 8 bits que maximiza la compatibilidad con ASCII;

UTF-16, una codificación de ancho variable de 16 bits;

UTF-32, una codificación de ancho fijo de 32 bits.

Estas son las tres codificaciones diferentes más populares.

  • En UTF-8 cada carácter se codifica en 1 a 4 bytes (la codificación dominante)
  • En UTF16 cada carácter se codifica en 1 a dos palabras de 16 bits y
  • en UTF-32, cada carácter se codifica como una sola palabra de 32 bits.
quikitina
fuente
1

Unicodees un estándar que proporciona un número único para cada personaje. Estos números únicos se denominan code points (que es solo un código único) a todos los caracteres existentes en el mundo (algunos todavía no se han agregado).

Para diferentes propósitos, es posible que deba representar esto code pointsen bytes (la mayoría de los lenguajes de programación lo hacen), y aquí es donde Character Encodingentra en juego.

UTF-8, UTF-16, UTF-32Y así sucesivamente son todos Character Encodings, y los puntos de código de Unicode están representados en estas codificaciones, de diferentes maneras.


UTF-8 la codificación tiene una longitud de ancho variable y los caracteres codificados pueden ocupar de 1 a 4 bytes inclusive;

UTF-16tiene una longitud variable y los caracteres, codificados, pueden tomar 1 o 2 bytes (que son 8 o 16 bits). Esto representa solo una parte de todos los caracteres Unicode llamados BMP (plano multilingüe básico) y es suficiente para casi todos los casos. Java usa UTF-16codificación para sus cadenas y caracteres;

UTF-32 tiene una longitud fija y cada carácter ocupa exactamente 4 bytes (32 bits).

Giorgi Tsiklauri
fuente