UTF-8, UTF-16 et UTF-32


487

Quelles sont les différences entre UTF-8, UTF-16 et UTF-32?

Je comprends qu'ils stockeront tous Unicode et que chacun utilise un nombre différent d'octets pour représenter un caractère. Y a-t-il un avantage à choisir l'un plutôt que l'autre?


36
Regardez cette vidéo si vous êtes intéressé par le fonctionnement d'Unicode youtube.com/watch?v=MijmeoH9LT4

1
La vidéo se concentre sur UTF-8, et oui, elle explique bien le fonctionnement de l'encodage à longueur variable et est principalement compatible avec les ordinateurs lisant ou écrivant uniquement en ASCII de longueur fixe. Les gars Unicode étaient intelligents lors de la conception de l'encodage UTF-8.
min le

1
J'ai créé un outil en ligne pour la conversion et la comparaison.
Amit Kumar Gupta

1
UTF-8 est la norme de facto dans la plupart des logiciels modernes pour les fichiers enregistrés . Plus précisément, c'est l'encodage le plus utilisé pour le HTML et les fichiers de configuration et de traduction (Minecraft, par exemple, n'accepte aucun autre encodage pour toutes ses informations textuelles). UTF-32 est rapide pour la représentation de la mémoire interne , et UTF-16 est un peu obsolète , actuellement utilisé uniquement dans Win32 pour des raisons historiques ( UTF-16 était de longueur fixe lorsque Windows 95 était une chose)
Kotauskas

@VladislavToncharov UTF-16 n'a jamais été un encodage de longueur fixe. Vous le confondez avec UCS-2.

Réponses:


373

UTF-8 présente un avantage dans le cas où les caractères ASCII représentent la majorité des caractères dans un bloc de texte, car UTF-8 les code en 8 bits (comme ASCII). Il est également avantageux en ce sens qu'un fichier UTF-8 contenant uniquement des caractères ASCII a le même codage qu'un fichier ASCII.

UTF-16 est meilleur là où ASCII n'est pas prédominant, car il utilise principalement 2 octets par caractère. UTF-8 commencera à utiliser 3 octets ou plus pour les caractères d'ordre supérieur où UTF-16 reste à seulement 2 octets pour la plupart des caractères.

UTF-32 couvrira tous les caractères possibles sur 4 octets. Cela le rend assez gonflé. Je ne vois aucun avantage à l'utiliser.


165
Avantage UTF-32: vous n'avez pas besoin de décoder les données stockées au point de code Unicode 32 bits pour, par exemple, la gestion caractère par caractère. Le point de code est déjà disponible dans votre tableau / vecteur / chaîne.
richq

22
Il est également plus facile d'analyser si (le ciel vous aide) vous devez réimplémenter la roue.
Paul McMillan

24
Eh bien, UTF-8 a un avantage dans les transferts réseau - pas besoin de s'inquiéter de l'endianité puisque vous transférez des données un octet à la fois (par opposition à 4).
Tim Čas

30
@richq Vous ne pouvez pas effectuer de gestion caractère par caractère en UTF-32, car le point de code ne correspond pas toujours à un caractère.
hamstergene

4
Avantage UTF-32: la manipulation des chaînes est peut-être plus rapide par rapport à l'équivalent utf-8
Wes

332

En bref:

  • UTF-8: encodage à largeur variable, rétrocompatible avec ASCII. Les caractères ASCII (U + 0000 à U + 007F) prennent 1 octet, les points de code U + 0080 à U + 07FF prennent 2 octets, les points de code U + 0800 à U + FFFF prennent 3 octets, les points de code U + 10000 à U + 10FFFF prendre 4 octets. Bon pour le texte anglais, pas si bon pour le texte asiatique.
  • UTF-16: encodage à largeur variable. Les points de code U + 0000 à U + FFFF prennent 2 octets, les points de code U + 10000 à U + 10FFFF prennent 4 octets. Mauvais pour le texte anglais, bon pour le texte asiatique.
  • UTF-32: encodage à largeur fixe. Tous les points de code prennent quatre octets. Un énorme porc de mémoire, mais rapide à opérer. Rarement utilisé.

En long: voir Wikipedia: UTF-8 , UTF-16 et UTF-32 .


65
@spurrymoses: Je me réfère strictement à la quantité d'espace occupée par les octets de données. UTF-8 nécessite 3 octets par caractère asiatique, tandis que UTF-16 ne nécessite que 2 octets par caractère asiatique. Ce n'est vraiment pas un problème majeur, car les ordinateurs ont des tonnes de mémoire de nos jours par rapport à la quantité moyenne de texte stockée dans la mémoire d'un programme.
Adam Rosenfield

12
UTF-32 n'est plus rarement utilisé ... sur osx et linux par wchar_tdéfaut à 4 octets. gcc a une option -fshort-wcharqui réduit la taille à 2 octets, mais rompt la compatibilité binaire avec les bibliothèques std.
vine'th

9
@PandaWood ofcource UTF-8 peut encoder n'importe quel personnage! Mais avez-vous comparé les besoins en mémoire avec ceux de l'UTF-16? Vous semblez manquer le but!
Ustaman Sangat

16
Si quelqu'un devait dire que l'UTF-8 n'est "pas si bon pour le texte asiatique" dans le contexte de tous les formats de codage, y compris ceux qui ne peuvent pas coder Unicode, ils auraient bien sûr tort. Mais ce n'est pas le contexte. Le contexte des besoins en mémoire vient du fait que la question (et la réponse) compare UTF-8, UTF-16 et UTF-32, qui encoderont tous du texte asiatique mais utiliseront différentes quantités de mémoire / stockage. Il s'ensuit que leur qualité relative serait naturellement entièrement dans le contexte des besoins en mémoire. "Pas si bon"! = "Pas bien".
Paul Gregory

5
@McGafter: Bien sûr que oui. Si vous voulez être digne de confiance, allez directement à la bouche du cheval au Consortium Unicode . Voir le chapitre 2.5 pour une description des encodages UTF- *. Mais pour obtenir une compréhension simple et de haut niveau des encodages, je trouve que les articles Wikipedia sont une source beaucoup plus accessible.
Adam Rosenfield

116
  • UTF-8 est variable de 1 à 4 octets.

  • UTF-16 est variable 2 ou 4 octets.

  • UTF-32 est fixé à 4 octets.

Remarque: UTF-8 peut prendre de 1 à 6 octets avec la dernière convention: https://lists.gnu.org/archive/html/help-flex/2005-01/msg00030.html


35
UTF8 est en fait de 1 à 6 octets.
Urkle

6
@Urkle est techniquement correct car le mappage de la gamme complète de UTF32 / LE / BE inclut U-00200000 - U-7FFFFFFF même si Unicode v6.3 se termine à U-0010FFFF inclus. Voici une belle répartition de l'encodage / déc 5 et 6 octets utf8: lists.gnu.org/archive/html/help-flex/2005-01/msg00030.html

4
en les sauvegardant avec des références pertinentes et leurs sources?
n611x007

20
@Urkle Non, UTF-8 ne peut pas avoir 5 ou 6 octets. Les points de code Unicode sont limités à 21 bits, ce qui limite UTF-8 à 4 octets. (Vous pouvez bien sûr étendre le principe de l'UTF-8 pour coder de grands nombres entiers arbitraires, mais ce ne serait pas Unicode.) Voir RFC 3629.
rdb

11
Citant Wikipedia: En novembre 2003, UTF-8 a été restreint par la RFC 3629 pour correspondre aux contraintes du codage de caractères UTF-16: l'interdiction explicite des points de code correspondant aux caractères de substitution haut et bas a supprimé plus de 3% des séquences de trois octets. et se terminant à U + 10FFFF a supprimé plus de 48% des séquences de quatre octets et toutes les séquences de cinq et six octets.
Adam Calvet Bohl

79

Unicode définit un énorme jeu de caractères unique, attribuant une valeur entière unique à chaque symbole graphique (ce qui est une simplification majeure et n'est pas vrai, mais il est suffisamment proche pour les besoins de cette question). UTF-8/16/32 sont simplement des façons différentes de coder cela.

En bref, UTF-32 utilise des valeurs 32 bits pour chaque caractère. Cela leur permet d'utiliser un code à largeur fixe pour chaque caractère.

UTF-16 utilise 16 bits par défaut, mais cela ne vous donne que 65 000 caractères possibles, ce qui est loin d'être suffisant pour l'ensemble Unicode complet. Certains caractères utilisent donc des paires de valeurs 16 bits.

Et UTF-8 utilise des valeurs de 8 bits par défaut, ce qui signifie que les 127 premières valeurs sont des caractères à octet unique de largeur fixe (le bit le plus significatif est utilisé pour signifier que c'est le début d'une séquence à plusieurs octets, laissant 7 bits pour la valeur réelle du caractère). Tous les autres caractères sont codés en séquences de 4 octets maximum (si la mémoire est utilisée).

Et cela nous amène aux avantages. Tout caractère ASCII est directement compatible avec UTF-8, donc pour la mise à niveau des applications héritées, UTF-8 est un choix courant et évident. Dans presque tous les cas, il utilisera également le moins de mémoire. D'un autre côté, vous ne pouvez pas garantir la largeur d'un caractère. Il peut avoir 1, 2, 3 ou 4 caractères de large, ce qui rend la manipulation des chaînes difficile.

UTF-32 est opposé, il utilise le plus de mémoire (chaque caractère a une largeur fixe de 4 octets), mais d'un autre côté, vous savez que chaque caractère a cette longueur précise, donc la manipulation des chaînes devient beaucoup plus simple. Vous pouvez calculer le nombre de caractères dans une chaîne simplement à partir de la longueur en octets de la chaîne. Vous ne pouvez pas faire ça avec UTF-8.

UTF-16 est un compromis. Il permet à la plupart des caractères de tenir dans une valeur 16 bits à largeur fixe. Donc, tant que vous n'avez pas de symboles chinois, de notes de musique ou d'autres, vous pouvez supposer que chaque caractère a une largeur de 16 bits. Il utilise moins de mémoire que l'UTF-32. Mais c'est à certains égards "le pire des deux mondes". Il utilise presque toujours plus de mémoire que UTF-8, et il n'évite toujours pas le problème qui afflige UTF-8 (caractères de longueur variable).

Enfin, il est souvent utile de simplement suivre ce que la plate-forme prend en charge. Windows utilise UTF-16 en interne, donc sur Windows, c'est le choix évident.

Linux varie un peu, mais ils utilisent généralement UTF-8 pour tout ce qui est compatible Unicode.

Donc, réponse courte: les trois codages peuvent coder le même jeu de caractères, mais ils représentent chaque caractère sous la forme de séquences d'octets différentes.


12
Il est inexact de dire que Unicode attribue un entier unique à chaque symbole graphique . Il les attribue à chaque point de code, mais certains points de code sont des caractères de contrôle invisibles et certains symboles graphiques nécessitent plusieurs points de code pour être représentés.
tchrist

15
@tchrist: oui, c'est inexact. Le problème est que pour expliquer avec précision Unicode, vous devez écrire des milliers de pages. J'espérais faire passer le concept de base pour expliquer la différence entre les encodages
jalf

@jalf lol à droite, donc pour expliquer Unicode, vous devrez écrire la spécification Unicode Core
Justin Ohms

@tchrist Plus précisément, vous pouvez construire des symboles chinois à partir des primitives fournies (mais ils sont dans le même graphique, vous finirez donc par utiliser une quantité irréelle d'espace - disque ou RAM - pour les encoder) au lieu d'utiliser le ceux intégrés.
Kotauskas

44

Unicode est un standard et sur UTF-x, vous pouvez le considérer comme une implémentation technique à des fins pratiques:

  • UTF-8 - " taille optimisée ": mieux adapté aux données basées sur les caractères latins (ou ASCII), il ne prend que 1 octet par caractère mais la taille augmente en conséquence la variété de symboles (et dans le pire des cas pourrait atteindre 6 octets par caractère)
  • UTF-16 - " balance ": il faut au moins 2 octets par caractère, ce qui est suffisant pour l'ensemble existant des langues dominantes avec une taille fixe pour faciliter la gestion des caractères (mais la taille est toujours variable et peut atteindre 4 octets par caractère )
  • UTF-32 - " performance ": permet d'utiliser des algorithmes simples à la suite de caractères de taille fixe (4 octets) mais avec un inconvénient de mémoire

«Langues traditionnelles» pas si courantes dans beaucoup de régions du monde ^^
tuxayo

2
UTF-16 est en fait optimisé en taille pour les caractères non ASCII. Car cela dépend vraiment avec quelles langues il sera utilisé.
tuxayo

@tuxayo est tout à fait d'accord, il convient de noter des ensembles de caractères Hanzi et Kanji pour la partie asiatique du monde.
tour

Devrait être la meilleure réponse. C'est trop correct pour être enterré ici.
Michal Štein

28

J'ai essayé de donner une explication simple dans mon blog .

UTF-32

nécessite 32 bits (4 octets) pour coder n'importe quel caractère. Par exemple, afin de représenter le point de code de caractère "A" à l'aide de ce schéma, vous devrez écrire 65 en nombre binaire 32 bits:

00000000 00000000 00000000 01000001 (Big Endian)

Si vous regardez de plus près, vous remarquerez que les sept bits les plus à droite sont en fait les mêmes bits lorsque vous utilisez le schéma ASCII. Mais comme UTF-32 est un schéma à largeur fixe , nous devons attacher trois octets supplémentaires. Cela signifie que si nous avons deux fichiers qui ne contiennent que le caractère "A", l'un est encodé en ASCII et l'autre est encodé en UTF-32, leur taille sera de 1 octet et 4 octets en conséquence.

UTF-16

Beaucoup de gens pensent que UTF-32 utilise une largeur fixe 32 bits pour représenter un point de code, UTF-16 est une largeur fixe 16 bits. FAUX!

En UTF-16, le point de code peut être représenté soit en 16 bits, soit en 32 bits. Donc, ce schéma est un système de codage de longueur variable. Quel est l'avantage sur l'UTF-32? Au moins pour ASCII, la taille des fichiers ne sera pas 4 fois celle d'origine (mais toujours deux fois), donc nous ne sommes toujours pas compatibles avec ASCII.

Puisque 7 bits sont suffisants pour représenter le caractère "A", nous pouvons désormais utiliser 2 octets au lieu de 4 comme l'UTF-32. Cela ressemblera à:

00000000 01000001

UTF-8

Vous avez deviné juste. En UTF-8, le point de code peut être représenté en utilisant 32, 16, 24 ou 8 bits, et en tant que système UTF-16, celui-ci est également un système de codage de longueur variable.

Enfin, nous pouvons représenter "A" de la même manière que nous le représentons en utilisant le système de codage ASCII:

01001101

Un petit exemple où UTF-16 est en fait meilleur que UTF-8:

Considérez la lettre chinoise "語" - son codage UTF-8 est:

11101000 10101010 10011110

Alors que son encodage UTF-16 est plus court:

10001010 10011110

Afin de comprendre la représentation et son interprétation, visitez le message d'origine.


19

UTF-8

  • n'a pas de concept d'ordre des octets
  • utilise entre 1 et 4 octets par caractère
  • ASCII est un sous-ensemble compatible d'encodage
  • complètement auto-synchronisé, par exemple un octet abandonné de n'importe où dans un flux corrompra au plus un seul caractère
  • à peu près toutes les langues européennes sont codées en deux octets ou moins par caractère

UTF-16

  • doit être analysé avec un ordre d'octet connu ou lire une marque d'ordre d'octet (BOM)
  • utilise 2 ou 4 octets par caractère

UTF-32

  • chaque caractère fait 4 octets
  • doit être analysé avec un ordre d'octet connu ou lire une marque d'ordre d'octet (BOM)

L'UTF-8 sera le plus économe en espace, sauf si la majorité des caractères proviennent de l'espace de caractères CJK (chinois, japonais et coréen).

UTF-32 est le meilleur pour l'accès aléatoire par décalage de caractères dans un tableau d'octets.


Comment fonctionne la «synchronisation automatique» en UTF-8? Pouvez-vous donner des exemples pour les caractères 1 octet et 2 octets?
Koray Tugay

2
@KorayTugay Les chaînes d'octets plus courtes valides ne sont jamais utilisées avec des caractères plus longs. Par exemple, ASCII est compris entre 0 et 127, ce qui signifie que tous les caractères à un octet ont la forme 0xxxxxxxbinaire. Tous les caractères à deux octets commencent 110xxxxxpar un deuxième octet de 10xxxxxx. Supposons donc que le premier caractère d'un caractère à deux octets soit perdu. Dès que vous voyez 10xxxxxxsans précédent 110xxxxxx, vous pouvez déterminer avec certitude qu'un octet a été perdu ou corrompu, et supprimer ce caractère (ou le demander à nouveau à partir d'un serveur ou autre), et continuer jusqu'à ce que vous voyiez à nouveau un premier octet valide .
Chris

1
si vous avez le décalage vers un caractère, vous avez le décalage vers ce caractère - utf8, utf16 ou utf32 fonctionnera de la même façon dans ce cas; c'est-à-dire qu'ils sont tous également bons à l'accès aléatoire par décalage de caractère dans un tableau d'octets. L'idée que utf32 est meilleur pour compter les caractères que utf8 est également complètement fausse. Un point de code (qui n'est pas le même qu'un caractère qui, encore une fois, n'est pas le même qu'un graphème .. soupir), a une largeur de 32 bits dans utf32 et entre 8 et 32 ​​bits dans utf8, mais un caractère peut s'étendre sur plusieurs points de code, ce qui détruit l'avantage majeur que les gens prétendent que utf32 a sur utf8.
Plus clair

14

J'ai fait quelques tests pour comparer les performances de la base de données entre UTF-8 et UTF-16 dans MySQL.

Vitesses de mise à jour

UTF-8

Entrez la description de l'image ici

UTF-16

Entrez la description de l'image ici

Insérer des vitesses

Entrez la description de l'image ici

Entrez la description de l'image ici

Supprimer les vitesses

Entrez la description de l'image ici

Entrez la description de l'image ici


14

En UTF-32, tous les caractères sont codés sur 32 bits. L'avantage est que vous pouvez facilement calculer la longueur de la chaîne. L'inconvénient est que pour chaque caractère ASCII, vous perdez trois octets supplémentaires.

En UTF-8, les caractères ont une longueur variable, les caractères ASCII sont codés sur un octet (huit bits), la plupart des caractères spéciaux occidentaux sont codés sur deux octets ou trois octets (par exemple, € est trois octets) et des caractères plus exotiques peuvent prendre à quatre octets. L'inconvénient évident est que, a priori, vous ne pouvez pas calculer la longueur d'une chaîne. Mais il faut beaucoup moins d'octets pour coder le texte de l'alphabet latin (anglais), par rapport à UTF-32.

UTF-16 est également de longueur variable. Les caractères sont codés sur deux octets ou quatre octets. Je ne vois vraiment pas l'intérêt. Il a l'inconvénient d'être de longueur variable, mais n'a pas l'avantage d'économiser autant d'espace que l'UTF-8.

De ces trois, UTF-8 est clairement le plus répandu.


Pourquoi voudrais-je calculer la longueur de la chaîne lors du développement de sites Web? Y a-t-il un avantage à choisir UTF-8 / UTF-16 dans le développement Web?
Morfidon

"L'avantage est que vous pouvez facilement calculer la longueur de la chaîne" Si vous définissez la longueur par le nombre de points de code, alors oui, vous pouvez simplement diviser la longueur en octets par 4 pour l'obtenir avec UTF-32. Ce n'est cependant pas une définition très utile: elle peut ne pas être liée au nombre de caractères. De plus, la normalisation peut modifier le nombre de points de code dans la chaîne. Par exemple, le mot français "été" peut être codé d'au moins 4 façons différentes, avec 3 longueurs de point de code distinctes.

UTF-16 est peut-être plus rapide que UTF-8 tout en ne gaspillant pas de mémoire comme le fait UTF-32.
Michal Štein

6

En fonction de votre environnement de développement, vous n'aurez peut-être même pas le choix de l'encodage de votre type de données de chaîne à utiliser en interne.

Mais pour stocker et échanger des données, j'utiliserais toujours UTF-8, si vous avez le choix. Si vous avez principalement des données ASCII, cela vous donnera la plus petite quantité de données à transférer, tout en étant capable de tout encoder. Optimiser pour le moins d'E / S est la voie à suivre sur les machines modernes.


On peut soutenir que le fait que l'UTF-8 est immunisé contre l'endianité est beaucoup plus important que les besoins d'espace. UTF-16 et UTF-32 devront inévitablement faire face à des problèmes d'endianité, où UTF-8 n'est qu'un flux d'octets.
IInspectable

2

Comme mentionné, la différence est principalement la taille des variables sous-jacentes, qui dans chaque cas s'agrandissent pour permettre à plus de caractères d'être représentés.

Cependant, les polices, l'encodage et les choses sont méchamment compliquées (inutilement?), Donc un gros lien est nécessaire pour remplir plus en détail:

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

Ne vous attendez pas à tout comprendre, mais si vous ne voulez pas avoir de problèmes plus tard, cela vaut la peine d'apprendre autant que vous le pouvez, le plus tôt possible (ou simplement demander à quelqu'un d'autre de le régler pour vous).

Paul.


ou utilisez simplement UTF-8 par défaut car il est devenu la norme de facto, et découvrez si un nouveau système le prend en charge ou non. si ce n'est pas le cas, vous pouvez revenir à ce message.
robotik

-2

En bref, la seule raison d'utiliser UTF-16 ou UTF-32 est de prendre en charge respectivement les scripts non anglais et anciens.

Je me demandais pourquoi quelqu'un choisissait d'avoir un encodage non UTF-8 alors qu'il est évidemment plus efficace à des fins Web / de programmation.

Une idée fausse courante - le nombre suffixé n'est PAS une indication de sa capacité. Ils prennent tous en charge l'Unicode complet, juste que l'UTF-8 peut gérer l'ASCII avec un seul octet, il est donc PLUS efficace / moins corruptible pour le CPU et sur Internet.

Quelques bonnes lectures: http://www.personal.psu.edu/ejp10/blogs/gotunicode/2007/10/which_utf_do_i_use.html et http://utf8everywhere.org


Je ne sais pas, pourquoi vous suggérez, que l'utilisation de UTF-16 ou UTF-32 devait prendre en charge le texte non anglais. UTF-8 peut très bien gérer cela. Et il y a aussi des caractères non ASCII dans le texte anglais. Comme un non-menuisier de largeur nulle. Ou un tiret em. J'ai peur, cette réponse n'ajoute pas beaucoup de valeur.
2018

Cette question est susceptible de diminuer le vote car UTF-8 est toujours couramment utilisé dans les fichiers HTML même si la majorité des caractères sont des caractères à 3 octets en UTF-8,
Ṃųỻịgǻňạcểơửṩ

Le support @IInspectable n'est pas la meilleure formulation, promouvoir ou un meilleur support serait plus précis
robotik

L'envoi d'une page comme utf8everywhere.org n'est pas ce que je ferais dans une réponse SO.
Michal Štein
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.