¿Cuántos bytes toma un personaje Unicode?

Estoy un poco confundido acerca de las codificaciones. Por lo que sé, los viejos caracteres ASCII tomaban un byte por personaje. ¿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 personaje?

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

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

No verá una respuesta simple porque no hay una.

En primer lugar, Unicode no contiene “todos los caracteres de todos los idiomas”, aunque sí lo intenta.

Unicode en sí mismo es una asignación, define puntos de código y un punto de código es un número, asociado generalmente con un carácter. Digo usualmente porque hay conceptos como combinar personajes. Puede que esté familiarizado con cosas como acentos o diéresis. Esos pueden usarse con otro personaje, como un a o un u para crear un nuevo personaje lógico. Por lo tanto, un personaje puede consistir en 1 o más puntos de código.

Para ser útil 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 codeunits. UTF-32 es la encoding 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 donde un punto de código necesitará múltiples unidades de código, o ese punto de código particular no se puede representar en absoluto en la encoding (esto es un problema, por ejemplo, con UCS-2).

Debido a la flexibilidad de combinar caracteres, incluso dentro de una encoding determinada, 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 personajes que tienen más de una representación (puede decir "an 'a' with an accent" que son 2 puntos de código, uno de los cuales es un carácter combinado o "accented 'a'" que es un punto de código )

Curiosamente, 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 bytes (1-3 continuation bytes) 110xxxxx 0xC0..0xDF First byte of a 2-byte character encoding 1110xxxx 0xE0..0xEF First byte of a 3-byte character encoding 11110xxx 0xF0..0xF4 First byte of a 4-byte character encoding 

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

Actualizar

Como prewett señaló, esta regla solo se aplica a UTF-8

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

Por lo que sé, los viejos caracteres ASCII tomaban un byte por personaje.

Derecha. En realidad, dado que ASCII es una encoding de 7 bits, admite 128 códigos (95 de los cuales son imprimibles), por lo que solo utiliza medio byte (si 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 todavía no.

Entonces, ¿cuántos bytes necesita por personaje?

Igual que su segunda pregunta.

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

No, esas son codificaciones. Definen cómo los bytes / octetos deberían 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 (reemplace 1F6AA con el punto de código en hexadecimal) para ver una imagen.

    • U + 0061 LETRA A MINÚSCULA LATINA: a
      • Nº: 97
      • UTF-8: 61
      • UTF-16: 00 61
    • U + 00A9 SEÑAL DE DERECHO DE AUTOR: ©
      • Nº: 169
      • UTF-8: C2 A9
      • UTF-16: 00 A9
    • U + 00AE SIGNO REGISTRADO: ®
      • Nº: 174
      • UTF-8: C2 AE
      • UTF-16: 00 AE
    • U + 1337 ETHIOPIC SYLLABLE PHWA:
      • 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 MUESTRA MUESTRA:
      • Nº: 8240
      • UTF-8: E2 80 B0
      • UTF-16: 20 30
    • U + 20AC EURO SIGN:
      • Nº: 8364
      • UTF-8: E2 82 AC
      • UTF-16: 20 AC
    • U + 2122 TRADE MARK SIGN:
      • Nº: 8482
      • UTF-8: E2 84 A2
      • UTF-16: 21 22
    • U + 2603 DE NIEVE:
      • 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
    • UMBRELLA 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
    • U + 269B ATOM SÍMBOLO:
      • Nº: 9883
      • UTF-8: E2 9A 9B
      • UTF-16: 26 9B
    • AEROPLANO U + 2708:
      • Nº: 9992
      • UTF-8: E2 9C 88
      • UTF-16: 27 08
    • U + 271E LA CRUZ LATINA BLANCA CON SOMBRAS:
      • Nº: 10014
      • UTF-8: E2 9C 9E
      • UTF-16: 27 1E
    • U + 3020 CARA POSTAL DE LA MARCA:
      • Nº: 12320
      • UTF-8: E3 80 A0
      • UTF-16: 30 20
    • U + 8089 CJK UNIFIED IDEOGRAPH-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

De acuerdo, me estoy dejando llevar …

Hechos graciosos:

  • Si está buscando un personaje específico, puede copiarlo y pegarlo en http://codepoints.net/ .
  • Perdí mucho tiempo en esta lista inútil (¡pero está ordenada!).
  • MySQL tiene un juego de caracteres llamado “utf8” que en realidad no admite caracteres de más de 3 bytes. Entonces no puedes insertar una stack de poo , el campo será truncado silenciosamente. Use “utf8mb4” en su lugar.
  • Hay una página de prueba de muñeco de nieve (unicodesnowmanforyou.com) .

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

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

UTF-8 es encoding 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 personaje tiene 4 bytes por caracteres.

UTF-16 usa 16 bits para cada personaje y representa solo una parte de los caracteres Unicode llamados BMP (para todos los propósitos prácticos es suficiente). Java usa esta encoding en sus cadenas.

En Unicode, la respuesta no es fácil. El problema, como ya has señalado, son las codificaciones.

Dada una 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 por dos.

La única encoding donde (a partir de ahora) podemos hacer la afirmación sobre el tamaño es UTF-32. Ahí siempre hay 32 bits por personaje, 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 usar 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 de lo que el número de bits que les da su nombre normalmente permitiría. Por ejemplo, el UTF-8 designa ciertos bytes que, por sí solos, no son válidos, pero cuando vayan seguidos de un byte de continuación válido permitirán describir un carácter más allá del rango de 8 bits de 0..255. Vea los ejemplos y codificaciones overlong a continuación en el artículo de Wikipedia sobre UTF-8.
    • El excelente ejemplo dado allí es que el carácter € (el punto de código U+20AC puede representarse como secuencia de tres bytes E2 82 AC o secuencia de cuatro bytes 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 encoding específica de Unicode, como UTF-8 o UTF-16.

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 está definido 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 encoding 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 UTF-32 puede.

Hay una gran herramienta para calcular los bytes de cualquier cadena en UTF-8: http://mothereff.in/byte-counter

Actualización: @mathias ha hecho público el código: https://github.com/mathiasbynens/mothereff.in/blob/master/byte-counter/eff.js

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

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

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

Para UTF-16, el personaje necesita cuatro bytes (dos unidades de código) si comienza con 0xD800 o superior; dicho personaje se llama “pareja sustituta”. Más específicamente, un par suplente 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, podría decirse).

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

Vea este convertidor de código Unicode . Por ejemplo, ingrese 0x2009 , donde 2009 es el número Unicode para el espacio delgado , en el campo “0x … notación” y haga clic en Convertir. El número hexadecimal E2 80 89 (3 bytes) aparece en el campo “Unidades de código UTF-8”.