Qu'est-ce que Unicode, UTF-8, UTF-16?


395

Quelle est la base d'Unicode et pourquoi le besoin d'UTF-8 ou UTF-16? J'ai fait des recherches sur Google et cherché ici aussi, mais ce n'est pas clair pour moi.

Dans VSS lors de la comparaison de fichiers, il y a parfois un message indiquant que les deux fichiers ont des UTF différents. Pourquoi en serait-il ainsi?

Veuillez expliquer en termes simples.



5
Cette FAQ du site Web officiel d'Unicode a des réponses pour vous.
Nemanja Trifunovic

4
@John: c'est une très belle introduction, mais ce n'est pas la source ultime: elle saute pas mal de détails (ce qui est bien pour un aperçu / introduction!)
Joachim Sauer

5
L'article est génial, mais il contient plusieurs erreurs et représente l'UTF-8 dans une lumière quelque peu conservatrice. Je suggère de lire utf8everywhere.org comme supplément.
Pavel Radzivilovsky

2
Jetez un œil à ce site: utf8everywhere.org
Vertexwahn

Réponses:


551

Pourquoi avons-nous besoin d'Unicode?

Au début (pas trop), tout ce qui existait était ASCII. Ce n'était pas grave, car il suffirait de quelques caractères de contrôle, de ponctuation, de chiffres et de lettres comme ceux de cette phrase. Malheureusement, le monde étrange actuel des intercommunications mondiales et des médias sociaux n'était pas prévu, et il n'est pas trop inhabituel de voir l'anglais, le العربية, le עִבְ, le עִבְרִית, le ελληνικά et le ភាសាខ្មែរ dans le même document (j'espère que je n'ai pas cassé de vieux navigateurs).

Mais pour l'argument, disons que Joe Average est un développeur de logiciels. Il insiste sur le fait qu'il n'aura besoin que de l'anglais et, en tant que tel, ne souhaite utiliser que l'ASCII. Cela peut convenir à Joe, l' utilisateur , mais ce ne l'est pas à Joe , développeur de logiciels . Environ la moitié du monde utilise des caractères non latins et l'utilisation de l'ASCII est sans doute inconsidérée pour ces personnes, et en plus de cela, il ferme son logiciel à une économie grande et en croissance.

Par conséquent, un jeu de caractères englobant comprenant toutes les langues est nécessaire. C'est ainsi qu'est venu Unicode. Il attribue à chaque caractère un numéro unique appelé point de code . Un avantage d'Unicode par rapport aux autres ensembles possibles est que les 256 premiers points de code sont identiques à ISO-8859-1 , et donc également ASCII. De plus, la grande majorité des caractères couramment utilisés ne sont représentables que sur deux octets, dans une région appelée le plan multilingue de base (BMP) . Maintenant, un encodage de caractères est nécessaire pour accéder à ce jeu de caractères, et comme la question le demande, je vais me concentrer sur UTF-8 et UTF-16.

Considérations sur la mémoire

Alors, combien d'octets donnent accès à quels caractères dans ces encodages?

  • UTF-8:
    • 1 octet: ASCII standard
    • 2 octets: arabe, hébreu, la plupart des scripts européens (notamment géorgien )
    • 3 octets: BMP
    • 4 octets: tous les caractères Unicode
  • UTF-16:
    • 2 octets: BMP
    • 4 octets: tous les caractères Unicode

Il convient de mentionner maintenant que les caractères ne figurant pas dans le BMP comprennent des scripts anciens, des symboles mathématiques, des symboles musicaux et des caractères chinois / japonais / coréens (CJK) plus rares .

Si vous travaillez principalement avec des caractères ASCII, alors UTF-8 est certainement plus efficace en mémoire. Cependant, si vous travaillez principalement avec des scripts non européens, l'utilisation de l'UTF-8 pourrait être jusqu'à 1,5 fois moins efficace en mémoire que l'UTF-16. Lorsque vous traitez de grandes quantités de texte, telles que de grandes pages Web ou de longs documents Word, cela peut affecter les performances.

Bases de l'encodage

Remarque: Si vous savez comment UTF-8 et UTF-16 sont codés, passez à la section suivante pour les applications pratiques.

  • UTF-8: Pour les caractères ASCII standard (0-127), les codes UTF-8 sont identiques. Cela rend l'UTF-8 idéal si une compatibilité descendante est requise avec le texte ASCII existant. Les autres caractères nécessitent entre 2 et 4 octets. Cela se fait en réservant quelques bits dans chacun de ces octets pour indiquer qu'il fait partie d'un caractère multi-octets. En particulier, le premier bit de chaque octet est 1destiné à éviter les conflits avec les caractères ASCII.
  • UTF-16: pour les caractères BMP valides, la représentation UTF-16 est simplement son point de code. Cependant, pour les caractères non BMP, UTF-16 introduit des paires de substitution . Dans ce cas, une combinaison de deux parties de deux octets correspond à un caractère non BMP. Ces portions de deux octets proviennent de la plage numérique BMP, mais sont garanties par la norme Unicode comme non valides en tant que caractères BMP. De plus, comme UTF-16 a deux octets comme unité de base, il est affecté par l' endianité . Pour compenser, une marque d'ordre d'octets réservés peut être placée au début d'un flux de données qui indique l'endianité. Ainsi, si vous lisez l'entrée UTF-16 et qu'aucune endianité n'est spécifiée, vous devez vérifier cela.

Comme on peut le voir, UTF-8 et UTF-16 sont loin d'être compatibles entre eux. Donc, si vous faites des E / S, assurez-vous de savoir quel encodage vous utilisez! Pour plus de détails sur ces encodages, veuillez consulter la FAQ UTF .

Considérations pratiques de programmation

Types de données de caractères et de chaînes: comment sont-ils codés dans le langage de programmation? S'ils sont des octets bruts, la minute où vous essayez de sortir des caractères non ASCII, vous pouvez rencontrer quelques problèmes. De plus, même si le type de caractère est basé sur un UTF, cela ne signifie pas que les chaînes sont du bon UTF. Ils peuvent autoriser des séquences d'octets illégales. En règle générale, vous devrez utiliser une bibliothèque qui prend en charge UTF, comme ICU pour C, C ++ et Java. Dans tous les cas, si vous souhaitez entrer / sortir autre chose que l'encodage par défaut, vous devrez d'abord le convertir.

Encodages recommandés / par défaut / dominants: lorsque vous avez le choix de l'UTF à utiliser, il est généralement préférable de suivre les normes recommandées pour l'environnement dans lequel vous travaillez. Par exemple, l'UTF-8 est dominant sur le Web, et depuis HTML5, il a été l' encodage recommandé . Inversement, les environnements .NET et Java sont basés sur un type de caractère UTF-16. De manière confuse (et incorrecte), des références sont souvent faites au "codage Unicode", qui fait généralement référence au codage UTF dominant dans un environnement donné.

Prise en charge des bibliothèques: les bibliothèques que vous utilisez prennent en charge une sorte d'encodage. Laquelle? Soutiennent-ils les cas d'angle? Étant donné que la nécessité est la mère de l'invention, les bibliothèques UTF-8 prennent généralement en charge correctement les caractères à 4 octets, car des caractères à 1, 2 et même 3 octets peuvent apparaître fréquemment. Cependant, toutes les bibliothèques UTF-16 prétendues ne prennent pas correctement en charge les paires de substitution, car elles se produisent très rarement.

Compter les caractères: Il existe des combinaisons de caractères en Unicode. Par exemple, le point de code U + 006E (n) et U + 0303 (un tilde combinant) forment ñ, mais le point de code U + 00F1 forme ñ. Ils devraient être identiques, mais un simple algorithme de comptage renverra 2 pour le premier exemple, 1 pour le second. Ce n'est pas nécessairement faux, mais ce n'est peut-être pas le résultat souhaité non plus.

Comparaison pour l'égalité: A, А et Α se ressemblent, mais ils sont respectivement latin, cyrillique et grec. Vous avez également des cas comme C et Ⅽ, l'un est une lettre, l'autre un chiffre romain. De plus, nous avons également à considérer les caractères de combinaison. Pour plus d'informations, voir Dupliquer les caractères dans Unicode .

Paires de substitution: elles apparaissent assez souvent sur SO, je vais donc fournir quelques exemples de liens:

Autres?:


11
Excellente réponse, grandes chances pour la prime ;-) Personnellement, j'ajouterais que certains plaident pour UTF-8 comme encodage de caractère universel , mais je sais que c'est une opinion qui n'est pas nécessairement partagée par tout le monde.
Joachim Sauer

3
Encore trop technique pour moi à ce stade. Comment le mot bonjour est-il stocké dans un ordinateur en UTF-8 et UTF-16?
FirstName LastName

1
Pourriez-vous développer davantage pourquoi, par exemple, le BMP prend 3 octets en UTF-8? J'aurais pensé que puisque sa valeur maximale est 0xFFFF (16 bits), cela ne prendrait que 2 octets pour y accéder.
marquez

2
@mark Certains bits sont réservés à des fins de codage. Pour un point de code qui prend 2 octets en UTF-8, il y a 5 bits réservés, ne laissant que 11 bits pour sélectionner un point de code. U + 07FF finit par être le point de code le plus élevé représentable sur 2 octets.
DPenner1

1
BTW - ASCII ne définit que 128 points de code, en utilisant seulement 7 bits pour la représentation. C'est ISO-8859-1 / ISO-8859-15 qui définit 256 points de code et utilise 8 bits pour la représentation. Les 128 premiers points de code dans tous ces 3 sont les mêmes.
Tuxdude

68
  • Unicode
    • est un ensemble de personnages utilisés dans le monde entier
  • UTF-8
    • un codage de caractères capable de coder tous les caractères possibles (appelés points de code) en Unicode.
    • l'unité de code est de 8 bits
    • utiliser une à quatre unités de code pour coder Unicode
    • 00100100 pour " $ " (un 8 bits); 11000010 10100010 pour " ¢ " (deux 8 bits); 11100010 10000010 10101100 pour " " (trois 8 bits)
  • UTF-16
    • un autre encodage de caractères
    • l'unité de code est de 16 bits
    • utiliser une à deux unités de code pour coder Unicode
    • 00000000 00100100 pour " $ " (un 16 bits); 11011000 01010010 11011111 01100010 pour " 𤭢 " (deux 16 bits)

1
Court et précis
Aritra Chatterjee

30

Unicode est une norme assez complexe. N'ayez pas trop peur, mais préparez-vous à un travail! [2]

Parce qu'une ressource crédible est toujours nécessaire, mais le rapport officiel est énorme, je suggère de lire ce qui suit:

  1. Le minimum absolu Chaque développeur de logiciels doit absolument, positivement, connaître Unicode et les jeux de caractères (sans excuses!) Une introduction de Joel Spolsky, PDG de Stack Exchange.
  2. Au BMP et au-delà! Un tutoriel par Eric Muller, directeur technique puis, vice-président plus tard, au Consortium Unicode. (20 premières diapositives et vous avez terminé)

Une brève explication:

Les ordinateurs lisent les octets et les gens lisent les caractères, nous utilisons donc des normes de codage pour mapper les caractères en octets. ASCII a été le premier standard largement utilisé, mais ne couvre que le latin (7 bits / caractère peut représenter 128 caractères différents). Unicode est une norme dont l'objectif est de couvrir tous les caractères possibles dans le monde (peut contenir jusqu'à 1114112 caractères, soit 21 bits / caractère max. L'Unicode 8.0 actuel spécifie 120737 caractères au total, et c'est tout).

La principale différence est qu'un caractère ASCII peut s'adapter à un octet (8 bits), mais la plupart des caractères Unicode ne le peuvent pas. Donc, des formes / schémas d'encodage (comme UTF-8 et UTF-16) sont utilisés, et le modèle de caractère se présente comme suit:

Chaque caractère détient une position énumérée de 0 à 1 114 111 (hex: 0-10FFFF) appelée point de code .
Un formulaire de codage mappe un point de code sur une séquence d'unité de code. Une unité de code est la façon dont vous souhaitez que les caractères soient organisés en mémoire, unités 8 bits, unités 16 bits, etc. UTF-8 utilise 1 à 4 unités de 8 bits et UTF-16 utilise 1 ou 2 unités de 16 bits pour couvrir la totalité de l'Unicode de 21 bits max. Les unités utilisent des préfixes pour repérer les limites des caractères, et plus d'unités signifient plus de préfixes qui occupent des bits. Ainsi, bien que UTF-8 utilise 1 octet pour le script latin, il a besoin de 3 octets pour les scripts ultérieurs dans Basic Multilingual Plane, tandis que UTF-16 utilise 2 octets pour tout cela. Et c'est leur principale différence.
Enfin, un schéma de codage (comme UTF-16BE ou UTF-16LE) mappe (sérialise) une séquence d'unité de code à une séquence d'octets.

caractère: π
point de code: U + 03C0
formes de codage (unités de code):
      UTF-8: CF 80
      UTF-16: 03C0
schémas de codage (octets):
      UTF-8: CF 80
      UTF-16BE: 03 C0
      UTF-16LE: C0 03

Astuce: un chiffre hexadécimal représente 4 bits, donc un nombre hexadécimal à deux chiffres représente un octet
Jetez également un œil aux cartes de plan dans Wikipedia pour avoir une idée de la disposition du jeu de caractères


19

À l'origine, Unicode était censé avoir un codage 16 bits à largeur fixe (UCS-2). Les premiers utilisateurs d'Unicode, comme Java et Windows NT, ont construit leurs bibliothèques autour de chaînes 16 bits.

Plus tard, la portée d'Unicode a été étendue pour inclure les caractères historiques, ce qui nécessiterait plus que les 65 536 points de code pris en charge par un codage 16 bits. Pour permettre aux caractères supplémentaires d'être représentés sur les plates-formes qui avaient utilisé UCS-2, le codage UTF-16 a été introduit. Il utilise des "paires de substitution" pour représenter les caractères dans les plans supplémentaires.

Pendant ce temps, de nombreux logiciels et protocoles réseau plus anciens utilisaient des chaînes 8 bits. UTF-8 a été conçu pour que ces systèmes puissent prendre en charge Unicode sans avoir à utiliser de caractères larges. Il est rétrocompatible avec ASCII 7 bits.


3
Il convient de noter que Microsoft se réfère toujours à l'UTF-16 comme Unicode, ajoutant à la confusion. Les deux ne sont pas les mêmes.
Mark Ransom

16

Cet article explique tous les détails http://kunststube.net/encoding/

ÉCRITURE POUR TAMPON

si vous écrivez dans un tampon de 4 octets, symbole avec codage UTF8, votre binaire ressemblera à ceci:

00000000 11100011 10000001 10000010

si vous écrivez dans un tampon de 4 octets, symbole avec codage UTF16, votre binaire ressemblera à ceci:

00000000 00000000 00110000 01000010

Comme vous pouvez le voir, selon la langue que vous utiliseriez dans votre contenu, cela affectera votre mémoire en conséquence.

Par exemple, pour ce symbole particulier: le codage UTF16 est plus efficace car nous avons 2 octets de rechange à utiliser pour le symbole suivant. Mais cela ne signifie pas que vous devez utiliser l'alphabet UTF16 pour le Japon.

LECTURE DU TAMPON

Maintenant, si vous voulez lire les octets ci-dessus, vous devez savoir dans quel encodage il a été écrit et le décoder correctement.

Par exemple, si vous décodez ceci: 00000000 11100011 10000001 10000010 en encodage UTF16, vous vous retrouverez avec pas

Remarque: l' encodage et Unicode sont deux choses différentes. Unicode est le grand (tableau) avec chaque symbole mappé à un point de code unique. Par exemple, le symbole (lettre) a un (point de code) : 30 42 (hex). Le codage, d'autre part, est un algorithme qui convertit les symboles de manière plus appropriée, lors du stockage sur le matériel.

30 42 (hex) - > UTF8 encoding - > E3 81 82 (hex), which is above result in binary.

30 42 (hex) - > UTF16 encoding - > 30 42 (hex), which is above result in binary.

entrez la description de l'image ici


12

Unicode est une norme qui mappe les caractères dans toutes les langues à une valeur numérique particulière appelée Points de code . La raison pour laquelle il le fait est qu'il permet à différents encodages d'être possibles en utilisant le même ensemble de points de code.

UTF-8 et UTF-16 sont deux de ces encodages. Ils prennent les points de code en entrée et les codent en utilisant une formule bien définie pour produire la chaîne codée.

Le choix d'un encodage particulier dépend de vos besoins. Différents encodages ont des besoins en mémoire différents et selon les caractères que vous allez traiter, vous devez choisir l'encodage qui utilise le moins de séquences d'octets pour encoder ces caractères.

Pour plus de détails sur Unicode, UTF-8 et UTF-16, vous pouvez consulter cet article,

Ce que tout programmeur doit savoir sur Unicode


9

Pourquoi unicode? Parce que ASCII n'a que 127 caractères. Ceux de 128 à 255 diffèrent selon les pays, c'est pourquoi il existe des pages de codes. Ils ont donc dit avoir jusqu'à 1114111 caractères. Alors, comment stockez-vous le point de code le plus élevé? Vous devrez le stocker en utilisant 21 bits, vous utiliserez donc un DWORD ayant 32 bits avec 11 bits gaspillés. Donc, si vous utilisez un DWORD pour stocker un caractère unicode, c'est le moyen le plus simple car la valeur de votre DWORD correspond exactement au point de code. Mais les tableaux DWORD sont bien sûr plus grands que les tableaux WORD et bien sûr encore plus grands que les tableaux BYTE. C'est pourquoi il y a non seulement utf-32, mais aussi utf-16. Mais utf-16 signifie un flux WORD, et un WORD a 16 bits, alors comment le point de code le plus élevé 1114111 peut-il s'intégrer dans un WORD? Ça ne peut pas! Ils ont donc mis tout ce qui est supérieur à 65535 dans un DWORD qu'ils appellent une paire de substitution. Ces paires de substitution sont deux MOTS et peuvent être détectées en regardant les 6 premiers bits. Qu'en est-il de l'utf-8? Il s'agit d'un tableau d'octets ou d'un flux d'octets, mais comment le point de code le plus élevé 1114111 peut-il s'intégrer dans un octet? Ça ne peut pas! D'accord, alors ils ont également mis un DWORD non? Ou peut-être un MOT, non? Presque juste! Ils ont inventé les séquences utf-8, ce qui signifie que chaque point de code supérieur à 127 doit être codé en une séquence de 2 octets, 3 octets ou 4 octets. Hou la la! Mais comment détecter de telles séquences? Eh bien, tout jusqu'à 127 est ASCII et est un seul octet. Ce qui commence par 110 est une séquence de deux octets, ce qui commence par 1110 est une séquence de trois octets et ce qui commence par 11110 est une séquence de quatre octets. Les bits restants de ces soi-disant "octets de départ" appartiennent au point de code. Maintenant, selon la séquence, les octets suivants doivent suivre. Un octet suivant commence par 10, les bits restants sont 6 bits de bits de charge utile et appartiennent au point de code. Concaténez les bits de charge utile du premier octet et des octets suivants et vous aurez le point de code. C'est toute la magie de l'utf-8.


3
Exemple utf-8 de signe € (Euro) décodé dans une séquence de 3 octets utf-8: E2 = 11100010 82 = 10000010 AC = 10101100 Comme vous pouvez le voir, E2 commence par 1110, c'est donc une séquence de trois octets Comme vous pouvez le voir , 82 ainsi que AC commencent par 10 donc ce sont les octets suivants Maintenant, nous concaténons les "bits de charge utile": 0010 + 000010 + 101100 = 10000010101100 qui est décimal 8364 Donc 8364 doit être le code pour le signe € (Euro).
brighty

5

ASCII - Le logiciel alloue seulement 8 octets en mémoire pour un caractère donné. Cela fonctionne bien pour les caractères anglais et adoptés (emprunteurs comme façade) car leurs valeurs décimales correspondantes tombent en dessous de 128 dans la valeur décimale. Exemple de programme C.

UTF-8 - Le logiciel alloue 1 à 4 octets variables de 8 bits pour un caractère donné. Qu'entend-on par variable ici? Supposons que vous envoyez le caractère «A» via vos pages HTML dans le navigateur (HTML est UTF-8), la valeur décimale correspondante de A est 65, lorsque vous le convertissez en décimal, il devient 01000010. Cela ne nécessite que 1 octet. , 1 octet de mémoire est alloué même pour les caractères anglais spéciaux adoptés comme «ç» dans une façade de mot. Cependant, lorsque vous souhaitez stocker des caractères européens, cela nécessite 2 octets, vous avez donc besoin d'UTF-8. Cependant, lorsque vous optez pour des caractères asiatiques, vous avez besoin d'un minimum de 2 octets et d'un maximum de 4 octets. De même, les Emoji nécessitent 3 à 4 octets. UTF-8 résoudra tous vos besoins.

UTF-16 allouera au minimum 2 octets et au maximum 4 octets par caractère, il n'allouera pas 1 ou 3 octets. Chaque caractère est représenté en 16 bits ou 32 bits.

Alors pourquoi existe UTF-16? À l'origine, Unicode était 16 bits et non 8 bits. Java a adopté la version originale de UTF-16.

En un mot, vous n'avez besoin d'UTF-16 nulle part à moins qu'il n'ait déjà été adopté par la langue ou la plateforme sur laquelle vous travaillez.

Le programme Java invoqué par les navigateurs Web utilise UTF-16 mais le navigateur Web envoie des caractères en utilisant UTF-8.


"Vous n'avez besoin d'UTF-16 nulle part à moins qu'il n'ait déjà été adopté par le langage ou la plate-forme": C'est un bon point mais voici une liste non inclusive: JavaScript, Java, .NET, SQL NCHAR, SQL NVARCHAR , VB4, VB5, VB6, VBA, VBScript, NTFS, API Windows….
Tom Blodget

2

UTF signifie acronyme de Unicode Transformation Format. Dans le monde actuel, il existe des scripts écrits dans des centaines d'autres langues, formats non couverts par l'ASCII de base utilisé précédemment. Par conséquent, UTF a vu le jour.

UTF-8 a des capacités de codage de caractères et son unité de code est de 8 bits tandis que pour UTF-16, elle est de 16 bits.

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.