UTF-8, UTF-16 et UTF-32
Quelles sont les différences entre UTF-8, UTF-16 et UTF-32?
Je comprends qu'ils seront tous magasin Unicode, et que chacun utilise un nombre différent d'octets pour représenter un caractère. Est-il un avantage à choisir l'un plutôt que l'autre?
12 réponses
UTF-8 a 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 Code tous les caractères en 8 bits (comme ASCII). Il est également avantageux qu'un fichier UTF-8 contenant uniquement des caractères ASCII ait le même codage qu'un fichier ASCII.
UTF-16 est meilleur lorsque L'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 dans 4 octets. Cela le rend assez gonflé. Je ne peux penser à aucun avantage à l'utiliser.
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 prennent 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 à utiliser. Rarement utilisé.
UTF-8 est variable 1 à 4 octets.
UTF-16 est variable 2 ou 4 octets.
UTF-32 est fixé 4 octets.
Unicode définit un seul jeu de caractères énorme, attribuant une valeur entière unique à chaque symbole graphique (c'est une simplification majeure, et ce n'est pas vrai, mais c'est assez proche pour les besoins de cette question). UTF-8/16/32 sont simplement différentes façons d'encoder cela.
En bref, UTF-32 utilise des valeurs de 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 65k possible caractères, ce qui est loin d'être suffisant pour L'ensemble Unicode complet. Ainsi, certains caractères utilisent des paires de valeurs de 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 à un octet de largeur fixe (le bit le plus significatif est utilisé pour signifier qu'il s'agit du début d'une séquence multi-octets, laissant 7 bits pour la valeur de caractère réelle). Tous les autres caractères sont codés sous forme de séquences allant jusqu'à 4 octets (si la mémoire sert).
Et cela nous amène à avantage. Tout ASCII-caractère est directement compatible avec UTF-8, donc pour la mise à niveau des applications héritées, UTF-8 est un choix commun et évident. Dans presque tous les cas, il utilisera également le moins de mémoire. D'un autre côté, vous ne pouvez pas faire de garanties sur la largeur d'un personnage. Il peut avoir 1, 2, 3 ou 4 caractères de large, ce qui rend la manipulation de chaîne difficile.
UTF-32 est opposé, il utilise le plus de mémoire (chaque caractère est fixe de 4 octets de large), mais d'autre part, vous sachez {[12] } que chaque caractère a cette longueur précise, donc la manipulation de chaîne devient beaucoup plus simple. Vous pouvez calculer le nombre de caractères dans une chaîne tout simplement de la longueur en octets de la chaîne. Vous ne pouvez pas faire cela avec UTF-8.
UTF-16 est un compromis. Il permet à la plupart des caractères de s'intégrer dans une valeur de 16 bits de 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 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 sévit dans UTF-8 (caractères de longueur variable).
Enfin, il est souvent utile d'aller avec 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 conforme à Unicode.
Réponse si courte: tous les trois les encodages peuvent encoder le même jeu de caractères, mais ils représentent chaque caractère comme des séquences d'octets différentes.
Unicode est un standard et à propos de UTF-X Vous pouvez penser comme une implémentation technique à des fins pratiques:
- UTF-8 - "taille optimisée ": le mieux adapté pour les données à base de caractères latins (ou ASCII), il ne prend que 1 octet par caractère, mais la taille augmente en conséquence la variété des 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 qui est assez pour l'ensemble existant des langages traditionnels 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 comme résultat de caractères de taille fixe (4 octets) mais avec un inconvénient de mémoire
J'ai essayé de donner une explication simple dans mon blogpost .
UTF-32
Nécessite 32 bits (4 octets) pour encoder n'importe quel caractère. Par exemple, pour représenter le point de code de caractère "A" en utilisant 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 corrects sont en fait les mêmes bits lors de l'utilisation du schéma ASCII. Mais puisque UTF-32 est schéma de largeur fixe , nous doit attacher trois octets supplémentaires. Ce qui 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 comme UTF-32 utilise une largeur fixe de 32 bits pour représenter un point de code, UTF-16 est une largeur fixe de 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 encodage de longueur variable système. Quel est l'avantage par rapport à L'UTF-32? Au moins pour ASCII, la taille des fichiers ne sera pas 4 fois l'original (mais toujours deux fois), donc nous ne sommes toujours pas ASCII rétrocompatible.
Puisque 7 bits suffisent pour représenter le caractère" A", nous pouvons maintenant utiliser 2 octets au lieu de 4 comme L'UTF-32. Cela ressemblera à:
00000000 01000001
UTF-8
Vous avez bien deviné.. 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 codage à longueur variable système.
Enfin, nous pouvons représenter "A" de la même manière que nous le représentons en utilisant un système de codage ASCII:
01001101
Un petit exemple où UTF-16 est réellement meilleur que UTF-8:
Considérons la lettre chinoise " 語 " - son encodage UTF-8 est:
11101000 10101010 10011110
Alors que son encodage UTF-16 est plus court:
10001010 10011110
Afin de comprendre la représentation et comment elle est interprétée, visitez le message original.
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 de l'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 byte-order connu ou lire un byte-order-mark (BOM)
- utilise 2 ou 4 octets par caractère
UTF-32
- chaque caractère est de 4 octets
- doit être analysé avec byte-order connu ou lire un byte-order-mark (BOM)
UTF-8 sera l'espace le plus efficace 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.
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
UTF-16
Insérer Des Vitesses
Supprimer Les Vitesses
En UTF-32, tous les caractères sont codés avec 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 gaspillez trois octets supplémentaires.
Dans les caractères UTF-8 ont une longueur variable, les caractères ASCII sont codés en un octet (huit bits), la plupart des caractères spéciaux occidentaux sont codés en deux octets ou trois octets (par exemple € est trois octets), et les caractères plus exotiques peuvent prendre jusqu'à quatre octets. Clair l'inconvénient est qu'a priori vous ne pouvez pas calculer la longueur de la 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 en deux octets ou en quatre octets. Je ne vois vraiment pas le point. Il a l'inconvénient d'être de longueur variable, mais n'a pas l'avantage d'économiser autant D'espace que UTF-8.
De ces trois, clairement UTF-8 est le plus largement répandu.
Selon votre environnement de développement, vous n'avez peut-être même pas le choix de l'encodage que votre type de données string utilisera 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. L'optimisation 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 deviennent plus grandes pour permettre à plus de caractères d'être représentés.
Cependant, les polices, l'encodage et les choses sont méchamment compliqués(inutilement?), donc un gros lien est nécessaire pour remplir plus de détail:
Http://www.cs.tut.fi/ ~ jkorpela/caractères. 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 pouvez, dès que vous le pouvez (ou quelqu'un d'autre pour faire le tri pour vous).
Paul.
En bref, la seule raison d'utiliser UTF-16 ou UTF-32 est de prendre en charge les scripts non-anglais et anciens respectivement.
Je me demandais pourquoi quelqu'un choisirait d'avoir un encodage non-UTF-8 alors qu'il est évidemment plus efficace à des fins de web/programmation.
Une idée fausse commune - le nombre suffixé N'est pas une indication de sa capacité. Ils prennent tous en charge L'Unicode complet, juste que UTF-8 peut gérer ASCII avec un seul octet, donc est 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