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?
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?
Réponses:
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.
En bref:
wchar_t
défaut à 4 octets. gcc a une option -fshort-wchar
qui réduit la taille à 2 octets, mais rompt la compatibilité binaire avec les bibliothèques std.
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
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.
Unicode est un standard et sur UTF-x, vous pouvez le considérer comme une implémentation technique à des fins pratiques:
J'ai essayé de donner une explication simple dans mon blog .
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.
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
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
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.
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.
0xxxxxxx
binaire. Tous les caractères à deux octets commencent 110xxxxx
par 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 10xxxxxx
sans 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 .
J'ai fait quelques tests pour comparer les performances de la base de données entre UTF-8 et UTF-16 dans MySQL.
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.
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.
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.
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