Combien de caractères peut encoder UTF-8?

97

Si UTF-8 est de 8 bits, cela ne signifie-t-il pas qu'il ne peut y avoir que 256 caractères différents au maximum?

Les 128 premiers points de code sont les mêmes qu'en ASCII. Mais il dit que UTF-8 peut prendre en charge jusqu'à un million de caractères?

Comment cela marche-t-il?

eMRe
la source
2
si vous pouviez réévaluer cette question, car toutes les réponses sont fausses. Lisez ma réponse: stackoverflow.com/a/45042566/124486
Evan Carroll
Dans les codages UTF-8, UTF-16, UTF-32 d'Unicode, le nombre est le nombre de bits dans ses unités de code , dont un ou plusieurs codent un point de code Unicode.
Tom Blodget
1
J'ai répondu à cette question il y a quelque temps pour tenter de la rectifier: ce serait bien si vous la compariez à la réponse choisie qui n'est littéralement qu'une seule citation de Wikipédia qui ne raconte pas toute l'histoire (j'espère que ma mise à jour est beaucoup plus clair)
Evan Carroll

Réponses:

135

UTF-8 n'utilise pas un octet tout le temps, c'est 1 à 4 octets.

Les 128 premiers caractères (US-ASCII) nécessitent un octet.

Les 1 920 caractères suivants ont besoin de deux octets pour être encodés. Cela couvre le reste de presque tous les alphabets latins, ainsi que les alphabets grec, cyrillique, copte, arménien, hébreu, arabe, syriaque et Tāna, ainsi que la combinaison des marques diacritiques.

Trois octets sont nécessaires pour les caractères dans le reste du plan multilingue de base, qui contient pratiquement tous les caractères d'usage courant [12], y compris la plupart des caractères chinois, japonais et coréens [CJK].

Quatre octets sont nécessaires pour les caractères dans les autres plans d'Unicode, qui incluent des caractères CJK moins courants, divers scripts historiques, des symboles mathématiques et des emoji (symboles pictographiques).

source: Wikipédia

zwippie
la source
salut @zwippie je suis nouveau dans ce domaine. Il y a quelque chose que je ne comprends pas.! BMP utilise 2 octets que vous dites est 3? ai-je tort?
chiperortiz
1
@chiperortiz, BMP est en effet 16 bits, il peut donc être encodé en UTF-16 avec une longueur constante par caractère (UTF-16 prend également en charge le dépassement de 16 bits, mais c'est une pratique difficile, et de nombreuses implémentations ne le supportent pas). Cependant, pour UTF-8, vous devez également encoder sa durée, vous perdez donc quelques bits. C'est pourquoi vous avez besoin de 3 octets pour encoder le BMP complet. Cela peut sembler inutile, mais rappelez-vous que UTF-16 utilise toujours 2 octets, mais UTF-8 utilise un octet par caractère pour la plupart des caractères latins. Le rendant deux fois plus compact.
sanderd17
L'idée maîtresse de la question du PO est liée à la raison pour laquelle on l'appelle UTF- 8 - cela ne répond pas vraiment à cela.
jbyrd
39

UTF-8 utilise 1 à 4 octets par caractère: un octet pour les caractères ascii (les 128 premières valeurs Unicode sont les mêmes que ascii). Mais cela ne nécessite que 7 bits. Si le bit le plus élevé ("signe") est mis à 1, cela indique le début d'une séquence multi-octets; le nombre de bits hauts consécutifs définis indique le nombre d'octets, puis un 0, et les bits restants contribuent à la valeur. Pour les autres octets, les deux bits les plus élevés seront 1 et 0 et les 6 bits restants sont pour la valeur.

Ainsi, une séquence de quatre octets commencerait par 11110 ... (et ... = trois bits pour la valeur) puis trois octets avec 6 bits chacun pour la valeur, produisant une valeur de 21 bits. 2 ^ 21 dépasse le nombre de caractères Unicode, donc tout l'Unicode peut être exprimé en UTF8.

CodeClown42
la source
@NickL. Non, je veux dire 3 octets. Dans cet exemple, si le premier octet d'une séquence multi-octets commence 1111, le premier 1 indique qu'il s'agit du début d'une séquence multi-octets, puis le nombre de 1 consécutifs après cela indique le nombre d' octets supplémentaires dans la séquence (donc un premier byte commencera soit 110, 1110 ou 11110).
CodeClown42
J'ai trouvé la preuve de vos propos dans la RFC 3629. tools.ietf.org/html/rfc3629#section-3 . Cependant, je ne comprends pas pourquoi dois-je placer "10" au début du deuxième octet 110xxxxx 10xxxxxx? Pourquoi pas seulement 110xxxxx xxxxxxxx?
kolobok
3
Réponse trouvée dans softwareengineering.stackexchange.com/questions/262227/… . Juste pour des raisons de sécurité (au cas où un seul octet au milieu du flux est corrompu)
kolobok
@kolobok Ah. Sans sécurité, vous pouvez alors encoder une valeur de 21 bits sur 3 octets (3 bits indiquant la longueur, plus 21 bits). : D Probablement ce n'est pas si significatif cependant, au moins les langues occidentales WRT.
CodeClown42
Je suppose que NickL a posé cette question, mais qu'est-il arrivé au reste des bits de ce premier octet si le ... représente les octets suivants au lieu de bits?
c6754
26

Selon ce tableau * UTF-8 devrait prendre en charge:

2 31 = 2.147.483.648 caractères

Cependant, la RFC 3629 a limité les valeurs possibles, donc maintenant nous sommes plafonnés à 4 octets , ce qui nous donne

2 21 = 2097152 caractères

Notez qu'une bonne partie de ces caractères est "réservée" à un usage personnalisé, ce qui est en fait assez pratique pour les polices d'icônes.

* Wikipédia a utilisé un tableau de 6 octets - ils ont depuis mis à jour l'article.

11/07/2017: Correction du double comptage du même point de code codé avec plusieurs octets

mpen
la source
Cette réponse compte deux fois le nombre d'encodages possibles. Une fois que vous avez compté tous les 2 ^ 7, vous ne pouvez plus les compter dans 2 ^ 11, 2 ^ 16, etc. Le nombre correct d'encodages possibles est 2 ^ 21 (bien que tous ne soient pas actuellement utilisés).
Jimmy
@Jimmy Tu es sûr que je compte deux fois? 0xxxxxxxdonne 7 bits utilisables, 110xxxxx 10xxxxxxdonne 11 de plus - il n'y a pas de chevauchement. Le premier octet commence par 0dans le premier cas et 1dans le second cas.
mpen
@mpen alors quel point de code 00000001stocke-t-il et que 11000000 100000001stocke-t-il?
Evan Carroll du
1
@EvanCarroll Euh ... point pris. Je ne savais pas qu'il y avait plusieurs façons d'encoder le même point de code.
mpen
1
J'ai essayé de répondre moi-même, voyez si vous pensez que c'est une meilleure explication et une meilleure réponse à la question: stackoverflow.com/a/45042566/124486
Evan Carroll
21

Unicode contre UTF-8

Unicode résout les points de code en caractères. UTF-8 est un mécanisme de stockage pour Unicode. Unicode a une spécification. UTF-8 a une spécification. Ils ont tous deux des limites différentes. UTF-8 a une limite ascendante différente.

Unicode

Unicode est désigné par «plans». Chaque plan porte 2 à 16 points de code. Il y a 17 plans en Unicode. Pour un total de 17 * 2^16points de code. Le premier plan, le plan 0 ou le BMP , est spécial par le poids de ce qu'il transporte.

Plutôt que d'expliquer toutes les nuances, laissez-moi simplement citer l'article ci-dessus sur les avions.

Les 17 avions peuvent accueillir 1 114 112 points de code. Parmi ceux-ci, 2 048 sont des substituts, 66 sont des non-caractères et 137 468 sont réservés à un usage privé, laissant 974 530 pour une affectation publique.

UTF-8

Revenons maintenant à l'article lié ci-dessus,

Le schéma de codage utilisé par UTF-8 a été conçu avec une limite beaucoup plus grande de 2 31 points de code (32 768 plans), et peut encoder 2 21 points de code (32 plans) même s'il est limité à 4 octets. [3] Comme Unicode limite les points de code aux 17 plans qui peuvent être encodés par UTF-16, les points de code au-dessus de 0x10FFFF ne sont pas valides en UTF-8 et UTF-32.

Vous pouvez donc voir que vous pouvez mettre des éléments dans UTF-8 qui ne sont pas Unicode valide. Pourquoi? Parce que UTF-8 accepte des points de code qu'Unicode ne prend même pas en charge.

UTF-8, même avec une limitation de quatre octets, prend en charge 2 21 points de code, ce qui est bien plus que17 * 2^16

Evan Carroll
la source
18

2 164 864 «caractères» peuvent être potentiellement codés par UTF-8.

Ce nombre est 2 ^ 7 + 2 ^ 11 + 2 ^ 16 + 2 ^ 21 qui vient du fonctionnement de l'encodage:

  • Les caractères 1 octet ont 7 bits pour le codage 0xxxxxxx(0x00-0x7F)

  • Les caractères à 2 octets ont 11 bits pour le codage 110xxxxx 10xxxxxx(0xC0-0xDF pour le premier octet; 0x80-0xBF pour le second)

  • Les caractères à 3 octets ont 16 bits pour le codage 1110xxxx 10xxxxxx 10xxxxxx(0xE0-0xEF pour le premier octet; 0x80-0xBF pour les octets de continuation)

  • Les caractères 4 octets ont 21 bits pour le codage 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx(0xF0-0xF7 pour le premier octet; 0x80-0xBF pour les octets de continuation)

Comme vous pouvez le voir, c'est beaucoup plus grand que l'Unicode actuel (1 112 064 caractères).

METTRE À JOUR

Mon calcul initial est faux car il ne tient pas compte de règles supplémentaires. Voir les commentaires sur cette réponse pour plus de détails.

Ruben Reyes
la source
2
Vos calculs ne respectent pas la règle UTF-8 selon laquelle seule la séquence d'unité de code la plus courte est autorisée à coder un point de code. Ainsi, 00000001 est valide pour U + 0001 mais 11110000 10000000 10000000 10000001 ne l'est pas. Réf: Tableau 3-7. Séquences d'octets UTF-8 bien formées . En outre, la question est directement répondue par le tableau: il suffit d'additionner les plages. (Ils sont disjoints pour exclure les substituts pour UTF-16).
Tom Blodget
Tom - merci pour votre commentaire! Je n'étais pas au courant de ces restrictions. J'ai vu le tableau 3-7 et j'ai couru les nombres et il semble qu'il y ait 1 083 392 séquences valides possibles.
Ruben Reyes
6

UTF-8 est un codage de longueur variable avec un minimum de 8 bits par caractère.
Les caractères avec des points de code plus élevés prendront jusqu'à 32 bits.

déceler
la source
2
C'est trompeur. Le point de code le plus long que vous puissiez avoir est 11110xxx 10xxxxxx 10xxxxxx 10xxxxxxdonc seulement 21 bits peuvent être utilisés pour coder le caractère réel.
Boris
5
J'ai dit que les points de code peuvent prendre jusqu'à 32 bits pour être encodés, je n'ai jamais prétendu que (par induction) vous pouviez encoder 2 ^ 32 caractères en UTF-8 32 bits. Mais c'est plutôt discutable, puisque vous pouvez encoder tous les caractères Unicode existants en UTF-8, et vous pouvez encoder encore plus si vous étirez UTF-8 à 48 bits (qui existe mais est obsolète), donc je ne suis pas sûr de ce que le point trompeur est.
deceze
2

Consultez la norme Unicode et les informations connexes, telles que leur entrée de FAQ, UTF-8 UTF-16, UTF-32 et BOM . Ce n'est pas si facile, mais ce sont des informations faisant autorité, et une grande partie de ce que vous pourriez lire sur UTF-8 ailleurs est discutable.

Le «8» dans «UTF-8» se rapporte à la longueur des unités de code en bits. Les unités de code sont des entités utilisées pour encoder des caractères, pas nécessairement comme un simple mappage un-à-un. UTF-8 utilise un nombre variable d'unités de code pour encoder un caractère.

La collection de caractères pouvant être encodés en UTF-8 est exactement la même que pour UTF-16 ou UTF-32, à savoir tous les caractères Unicode. Ils encodent tous tout l'espace de codage Unicode, qui comprend même des non-caractères et des points de code non attribués.

Jukka K. Korpela
la source
1

Bien que je sois d'accord avec mpen sur les codes UTF-8 maximum actuels (2164864) (énumérés ci-dessous, je ne peux pas commenter le sien), il est décalé de 2 niveaux si vous supprimez les 2 restrictions majeures de UTF-8: seulement 4 octets limite et les codes 254 et 255 ne peuvent pas être utilisés (il n'a supprimé que la limite de 4 octets).

Le code de départ 254 suit la disposition de base des bits de départ (indicateur multi-bits mis à 1, un compte de 6 1 et terminal 0, pas de bits de réserve) vous donnant 6 octets supplémentaires avec lesquels travailler (6 groupes 10xxxxxx, 2 ^ supplémentaires 36 codes).

Le code de départ 255 ne suit pas exactement la configuration de base, pas de terminal 0 mais tous les bits sont utilisés, ce qui vous donne 7 octets supplémentaires (indicateur multi-bits mis à 1, un compte de 7 1 et pas de terminal 0 car tous les bits sont utilisés ; 7 groupes 10xxxxxx, 2 ^ 42 codes supplémentaires).

L'ajout de ces derniers donne un jeu de caractères présentable maximum final de 4 468 982 745 216. C'est plus que tous les caractères utilisés actuellement, les langues anciennes ou mortes et toutes les langues supposées perdues. Script angélique ou céleste quelqu'un?

Il existe également des codes à un octet qui sont ignorés / ignorés dans la norme UTF-8 en plus de 254 et 255: 128-191, et quelques autres. Certains sont utilisés localement par le clavier, l'exemple de code 128 est généralement un retour arrière de suppression. Les autres codes de démarrage (et les plages associées) ne sont pas valides pour une ou plusieurs raisons ( https://en.wikipedia.org/wiki/UTF-8#Invalid_byte_sequences ).

James V. Fields
la source
0

Unicode est fermement marié à UTF-8. Unicode prend spécifiquement en charge 2 ^ 21 points de code (2097152 caractères), ce qui correspond exactement au même nombre de points de code pris en charge par UTF-8. Les deux systèmes réservent le même espace `` mort '' et des zones restreintes pour les points de code, etc. ... depuis juin 2018, la version la plus récente, Unicode 11.0, contient un répertoire de 137439 caractères

De la norme Unicode. FAQ Unicode

La norme Unicode encode les caractères dans la plage U + 0000..U + 10FFFF, ce qui équivaut à un espace de code de 21 bits.

À partir de la page Wikipedia UTF-8. Description de l'UTF-8

Depuis la restriction de l'espace de code Unicode à des valeurs de 21 bits en 2003, UTF-8 est défini pour encoder des points de code dans un à quatre octets, ...

Afficher un nom
la source
21 bits sont arrondis. Unicode prend en charge 1 114 112 points de code (U + 0000 à U + 10FFFF) comme il le dit. (Parfois décrit comme 17 avions de 65536.)
Tom Blodget
@TomBlodget, vous avez raison. la conclusion la plus pertinente de cette discussion est que UTF-8 peut encoder tous les points actuellement définis dans la norme Unicode et sera probablement capable de le faire pendant un certain temps encore.
Afficher le nom