Combien d'octets un caractère Unicode prend-il?

239

Je suis un peu confus au sujet des encodages. Autant que je sache, les anciens caractères ASCII prenaient un octet par caractère. De combien d'octets un caractère Unicode a-t-il besoin?

Je suppose qu'un caractère Unicode peut contenir tous les caractères possibles de n'importe quelle langue - ai-je raison? Alors, de combien d'octets a-t-il besoin par caractère?

Et que signifient UTF-7, UTF-6, UTF-16, etc.? S'agit-il de différentes versions d'Unicode?

J'ai lu l'article Wikipedia sur Unicode mais c'est assez difficile pour moi. J'ai hâte de voir une réponse simple.

nan
la source
15
Désolé, il n'y a pas de réponse simple. Je trouve le tout un peu en désordre. Unicode a été facturé comme utilisant deux octets et capable de représenter tous les caractères, mais il s'avère que deux octets ne suffisaient pas.
Jonathan Wood
12
"Réponse simple": un caractère unicode prend 1 à 4 octets. Unicode couvre beaucoup de langues mais pas toutes. La dernière fois que j'ai regardé, par exemple, Klingon n'était pas un jeu de caractères Unicode officiel.
Peter G.
9
Klingon ne fait pas partie du standard Unicode lui-même, non. Il utilise à la place la zone d'utilisation privée d'Uniode (U + F8D0 - U + F8FF).
Remy Lebeau
1
Question du Sauveur - merci. Ma situation est de stocker des données via des LMS conformes à SCORM 1.2 ... la norme pour SCORM 1.2 'cmi.suspend_data' est de 4096 octets de données qu'un développeur précédent a supposé que nous pouvions stocker 4096 caractères. Oh mec, il avait tort - je viens de découvrir pourquoi notre bookmarking échoue sur de longs cours. Alors maintenant, je sais que puisque nous utilisons UTF-8, cela prend 4 octets par caractère, ce qui nous donne 1024 caractères.
danjah

Réponses:

147

Vous ne verrez pas de réponse simple car il n'y en a pas.

Tout d'abord, Unicode ne contient pas "tous les caractères de toutes les langues", bien qu'il essaie bien sûr.

Unicode lui-même est un mappage, il définit des points de code et un point de code est un nombre, généralement associé à un caractère. Je dis généralement parce qu'il existe des concepts comme la combinaison de personnages. Vous connaissez peut-être des choses comme les accents ou les trémas. Ceux-ci peuvent être utilisés avec un autre caractère, comme un aou un upour créer un nouveau caractère logique. Un caractère peut donc consister en un ou plusieurs points de code.

Pour être utile dans les systèmes informatiques, nous devons choisir une représentation pour ces informations. Ce sont les différents codages Unicode, tels que utf-8, utf-16le, utf-32 etc. Ils se distinguent largement par la taille de leurs unités de codage. UTF-32 est le codage le plus simple, il a une unité de codage de 32 bits, ce qui signifie qu'un point de code individuel s'intègre confortablement dans une unité de codage. Les autres encodages auront des situations où un point de code aura besoin de plusieurs unités de codage, ou ce point de code particulier ne peut pas du tout être représenté dans l'encodage (c'est un problème par exemple avec UCS-2).

En raison de la flexibilité de la combinaison de caractères, même dans un codage donné, le nombre d'octets par caractère peut varier en fonction du caractère et de la forme de normalisation. Il s'agit d'un protocole pour traiter les caractères qui ont plus d'une représentation (vous pouvez dire "an 'a' with an accent"qui est 2 points de code, dont l'un est un caractère de combinaison ou "accented 'a'"qui est un point de code).

Logan Capaldo
la source
1
D'ACCORD. Alors combien d'octets prend un caractère donné représenté dans un point de code donné? Par exemple, l'espace insécable.
Nicolas Barbulesco
Les caractères de combinaison font de la vie d'un programmeur un enfer quand il s'agit d'écrire strlen (), substr () et d'autres fonctions de manipulation de chaînes sur des tableaux UTF8. Ce genre de travail ne sera jamais complet et toujours bogué.
Nulik
J'ai écrit une démo qui montre les fichiers encodés Windows-1252, UTF8 et UTF8-BOM interprétés avec chaque encodage, et compare l'égalité entre les résultats: github.com/vladyrn/encodings_demo
Vlad
195

Curieusement, personne n'a indiqué comment calculer le nombre d'octets prenant un caractère Unicode. Voici la règle pour les chaînes codées 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

Donc, la réponse rapide est: cela prend 1 à 4 octets, selon le premier qui indiquera combien d'octets cela prendra.

paul.ago
la source
8
Je crois que la valeur hexadécimale maximale pour un caractère à 4 octets est 0xF7 (pas 0xF4).
DJPJ
Merci beaucoup! Je contrôlais simplement + f'ing à travers la norme IETF, et je n'ai rien trouvé sur l'encodage, et l'article que je lisais n'est pas entré dans assez de détails pour dire combien de bits sont utilisés pour représenter le nombre de code de fin points par "personnage".
MarcusJ
1
Ceci est maintenant sur la deuxième page de ma feuille de triche "introduction pour les nouveaux membres de l'équipe", avec les deux premiers commentaires hilarants
Cee McSharpface
1
0xF4 n'était pas une erreur mais une clarification. Les points de code Unicode sont dans la plage 0-0x10ffff, donc le dernier point de code est codé F4 8F BF BF.
Frediano Ziglio
38

Je sais que cette question est ancienne et a déjà une réponse acceptée, mais je veux offrir quelques exemples (en espérant que cela sera utile à quelqu'un).

Autant que je sache, les anciens caractères ASCII prenaient un octet par caractère.

Droite. En fait, comme ASCII est un codage 7 bits, il prend en charge 128 codes (dont 95 sont imprimables), il n'utilise donc qu'un demi-octet (si cela a du sens).

De combien d'octets un caractère Unicode a-t-il besoin?

Unicode mappe simplement les caractères aux points de code. Il ne définit pas comment les coder. Un fichier texte ne contient pas de caractères Unicode, mais des octets / octets qui peuvent représenter des caractères Unicode.

Je suppose qu'un caractère Unicode peut contenir tous les caractères possibles de n'importe quelle langue - ai-je raison?

Non, mais presque. Donc, fondamentalement, oui. Mais toujours non.

Alors, de combien d'octets a-t-il besoin par caractère?

Identique à votre 2e question.

Et que signifient UTF-7, UTF-6, UTF-16, etc.? S'agit-il de versions Unicode?

Non, ce sont des encodages. Ils définissent comment les octets / octets doivent représenter les caractères Unicode.

Quelques exemples. Si certains d'entre eux ne peuvent pas être affichés dans votre navigateur (probablement parce que la police ne les prend pas en charge), accédez à http://codepoints.net/U+1F6AA(remplacer 1F6AApar le point de code en hexadécimal) pour voir une image.

    • U + 0061 LETTRE MINUSCULE LATINE A: a
      • Nº: 97
      • UTF-8: 61
      • UTF-16: 00 61
    • SIGNE DE DROIT D'AUTEUR U + 00A9: ©
      • Nº: 169
      • UTF-8: C2 A9
      • UTF-16: 00 A9
    • SIGNE ENREGISTRÉ U + 00AE: ®
      • Nº: 174
      • UTF-8: C2 AE
      • UTF-16: 00 AE
    • U + 1337 PHWA SYLLABLE ETHIOPIQUE:
      • 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 PAR MILLE SIGN:
      • Nº: 8240
      • UTF-8: E2 80 B0
      • UTF-16: 20 30
    • SIGNE EURO U + 20AC:
      • Nº: 8364
      • UTF-8: E2 82 AC
      • UTF-16: 20 AC
    • SIGNE DE MARQUE 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
    • TÉLÉPHONE NOIR U + 260E:
      • Nº: 9742
      • UTF-8: E2 98 8E
      • UTF-16: 26 0E
    • U + 2614 PARAPLUIE AVEC GOUTTES DE PLUIE:
      • Nº: 9748
      • UTF-8: E2 98 94
      • UTF-16: 26 14
    • U + 263A VISAGE BLANC SOURIANT:
      • Nº: 9786
      • UTF-8: E2 98 BA
      • UTF-16: 26 3A
    • U + 2691 DRAPEAU NOIR:
      • Nº: 9873
      • UTF-8: E2 9A 91
      • UTF-16: 26 91
    • U + 269B SYMBOLE ATOM:
      • Nº: 9883
      • UTF-8: E2 9A 9B
      • UTF-16: 26 9B
    • AVION U + 2708:
      • Nº: 9992
      • UTF-8: E2 9C 88
      • UTF-16: 27 08
    • CROIX LATINE BLANCHE OMBRÉE U + 271E:
      • Nº: 10014
      • UTF-8: E2 9C 9E
      • UTF-16: 27 1E
    • U + 3020 VISAGE DE LA MARQUE POSTALE:
      • Nº: 12320
      • UTF-8: E3 80 A0
      • UTF-16: 30 20
    • U + 8089 CJK IDÉOGRAPHE UNIFIÉ-8089:
      • Nº: 32905
      • UTF-8: E8 82 89
      • UTF-16: 80 89
    • U + 1F4A9 PILE 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

D'accord, je m'emballe ...

Faits amusants:

basic6
la source
Les unités de code en UTF-16 ont une largeur de 16 bits. Vous leur avez montré un espace au milieu, ce qui est trompeur. La représentation UTF-16 pour © devrait plutôt être à la 00A9place de 00 A9(qui serait UTF-16BE).
Roland Illig
Quelle est la différence? NE signifie pas big endian? Il l'a écrit en big endian, et donc un fichier écrit en big endian UTF-16 serait le même que UTF-16BE, non?
HappyPandaFace
6
Corrections: 1) ASCII est de 7 bits, un octet est de 8 bits, c'est donc beaucoup plus que la moitié. 2) Unicode définit comment coder les points de code. UTF-8, UTF-16 et UTF-32 sont définis dans la norme Unicode.
Jonathan Rosenne
3
@JonathanRosenne Je pense qu'il / elle voulait dire qu'il n'utilise que la moitié des valeurs possibles représentables avec 8 bits, pas qu'il utilise la moitié des bits.
Aritz Lopez
2
J'aime vraiment les exemples. Ils soulignent pourquoi on peut préférer l'UTF-16 à l'UTF-8, par exemple. Les développeurs de différents logiciels peuvent sélectionner différents encodages en fonction des caractères Unicode les plus susceptibles d'être utilisés. En Chine / Japon par exemple, UTF-16 (2 octets) a plus de sens que UTF-8 pour eux, car les mêmes caractères auraient souvent besoin de deux fois plus d'octets pour encoder en UTF-8
Mike
29

Pour parler simplement Unicode est une norme qui attribue un numéro (appelé point de code) à tous les personnages du monde (son travail est toujours en cours).

Maintenant, vous devez représenter ces points de code en utilisant des octets, c'est ce qu'on appelle character encoding.UTF-8, UTF-16, UTF-6sont des moyens de représenter ces personnages.

UTF-8est un codage de caractères multi-octets. Les caractères peuvent avoir de 1 à 6 octets (certains d'entre eux ne sont peut-être pas nécessaires pour le moment).

UTF-32 chaque caractère a 4 octets par caractère.

UTF-16utilise 16 bits pour chaque caractère et il ne représente qu'une partie des caractères Unicode appelés BMP (à toutes fins pratiques, cela suffit). Java utilise cet encodage dans ses chaînes.

Zimbabwe
la source
10
Unicode est un ensemble de codes 21 bits et 4 octets suffisent pour représenter n'importe quel caractère Unicode en UTF-8. UTF-16 utilise des substituts pour représenter des caractères en dehors du BMP (plan multilingue de base); il a besoin de 2 ou 4 octets pour représenter tout caractère Unicode valide. UCS-2 était la seule variante 16 bits d'UTF-16 sans prise en charge des substituts ou des caractères en dehors du BMP.
Jonathan Leffler
1
Vous avez raison. L'original UTF-8 avait 6 octets pour accueillir un 32 bits. En fait, je ne voulais pas compliquer les choses car il était déjà confondu avec le doc wiki :)
Zimbabwe
3
Cette réponse indique que UTF-16 ne peut pas coder les points de code BMP. Ceci est incorrect, car ceux-ci peuvent être encodés comme ils le peuvent en UTF-8 en utilisant des paires de substitution. (Vous devez penser à l'UCS-2 obsolète, avant la sortie d'Unicode 2.0, qui codait uniquement les points de code 16 bits.) De plus, Java n'utilise pas tout à fait l'UTF-16, il en utilise une forme modifiée où le code pointe 0 est codé différemment.
rdb
@rdb - C'est le contraire. La réponse dit que l'UTF-16 représente le BMP.
Nicolas Barbulesco
3
J'ai mal tapé; J'avais voulu dire "non-BMP". L'erreur dans la réponse est qu'elle indique que UTF-16 représente des caractères BMP, ce qui est inexact. UTF-16 peut coder tous les caractères unicode - les caractères non BMP sont codés via des paires de substitution. Peut-être que le répondeur a été confondu avec 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 est le dernier point de code unicode par définition, et il est défini de cette façon parce que c'est la limite technique de l'UTF-16.

C'est également le plus grand point de code UTF-8 peut coder en 4 octets, mais l'idée derrière le codage UTF-8 fonctionne également pour les codages 5 et 6 octets pour couvrir les points de code jusqu'à 7FFFFFFF, c'est-à-dire. la moitié de ce que l'UTF-32 peut.

John
la source
8

En Unicode, la réponse n'est pas facile à donner. Le problème, comme vous l'avez déjà souligné, concerne les encodages.

Étant donné toute phrase en anglais sans caractères diacritiques, la réponse pour UTF-8 serait autant d'octets que de caractères et pour UTF-16, ce serait le nombre de caractères multiplié par deux.

Le seul encodage où (à partir de maintenant) nous pouvons faire la déclaration sur la taille est UTF-32. Là, c'est toujours 32 bits par caractère, même si j'imagine que des points de code sont préparés pour un futur UTF-64 :)

Ce qui le rend si difficile, ce sont au moins deux choses:

  1. caractères composés, où au lieu d'utiliser l'entité de caractère déjà accentuée / diacritique (À), un utilisateur a décidé de combiner l'accent et le caractère de base (`A).
  2. points de code. Les points de code sont la méthode par laquelle les codages UTF permettent de coder plus que le nombre de bits qui leur donne leur nom ne le permet habituellement. Par exemple, UTF-8 désigne certains octets qui en eux-mêmes ne sont pas valides, mais lorsqu'ils sont suivis d'un octet de continuation valide, ils permettront de décrire un caractère au-delà de la plage de 8 bits de 0..255. Voir les exemples et les encodages superposés ci-dessous dans l'article Wikipedia sur UTF-8.
    • L'excellent exemple donné il y a que le caractère € (point de code U+20ACpeut être représenté soit sous forme de trois octets séquence E2 82 ACou quatre octets séquence F0 82 82 AC.
    • Les deux sont valides, et cela montre à quel point la réponse est compliquée lorsqu'on parle de "Unicode" et non d'un codage spécifique de Unicode, tel que UTF-8 ou UTF-16.
0xC0000022L
la source
4

Eh bien, je viens de tirer la page Wikipedia dessus, et dans la partie d'introduction, j'ai vu "Unicode peut être implémenté par différents encodages de caractères. Les encodages les plus couramment utilisés sont UTF-8 (qui utilise un octet pour tous les caractères ASCII, qui ont les mêmes valeurs de code dans le codage UTF-8 et ASCII, et jusqu'à quatre octets pour les autres caractères), le désormais obsolète UCS-2 (qui utilise deux octets pour chaque caractère mais ne peut pas coder tous les caractères dans la norme Unicode actuelle) "

Comme le montre cette citation, votre problème est que vous supposez qu'Unicode est un moyen unique de coder les caractères. Il existe en fait plusieurs formes d'Unicode, et, encore une fois dans cette citation, l'une d'entre elles a même 1 octet par caractère, tout comme ce à quoi vous êtes habitué.

Donc, votre réponse simple que vous voulez est que cela varie.

Loduwijk
la source
3

Pour UTF-16, le caractère a besoin de quatre octets (deux unités de code) s'il commence par 0xD800 ou plus; un tel personnage est appelé «paire de substitution». Plus précisément, une paire de substitution a la forme:

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

où [...] indique une unité de code à deux octets avec la plage donnée. Tout <= 0xD7FF est une unité de code (deux octets). N'importe quoi> = 0xE000 n'est pas valide (sauf les marqueurs de nomenclature, sans doute).

Voir http://unicodebook.readthedocs.io/unicode_encodings.html , section 7.5.

prewett
la source
1

De Wiki:

UTF-8, un codage à largeur variable 8 bits qui maximise la compatibilité avec ASCII;

UTF-16, un codage 16 bits à largeur variable;

UTF-32, un codage 32 bits à largeur fixe.

Ce sont les trois encodages différents les plus populaires.

  • En UTF-8, chaque caractère est codé en 1 à 4 octets (le codage dominant)
  • En UTF16, chaque caractère est codé en 1 à deux mots de 16 bits et
  • en UTF-32, chaque caractère est codé comme un seul mot de 32 bits.
chikitine
la source
1

Unicodeest une norme qui fournit un numéro unique pour chaque personnage. Ces numéros uniques sont appelés code points (qui est juste un code unique) pour tous les caractères existant dans le monde (certains doivent encore être ajoutés).

À différentes fins, vous devrez peut-être le représenter code pointsen octets (la plupart des langages de programmation le font), et voici où Character Encodingintervient.

UTF-8, UTF-16, UTF-32Et ainsi de suite sont tous Character Encodings, et les points de code Unicode sont représentés dans ces codages, de différentes façons.


UTF-8 le codage a une longueur à largeur variable et les caractères qui y sont codés peuvent occuper de 1 à 4 octets inclus;

UTF-16a une longueur variable et les caractères codés peuvent prendre 1 ou 2 octets (soit 8 ou 16 bits). Cela ne représente qu'une partie de tous les caractères Unicode appelés BMP (Basic Multilingual Plane) et c'est suffisant pour presque tous les cas. Java utilise l' UTF-16encodage pour ses chaînes et caractères;

UTF-32 a une longueur fixe et chaque caractère prend exactement 4 octets (32 bits).

Giorgi Tsiklauri
la source