UTF-16 - UTF-16

UTF-16
Carte complète Unifont.png
Les 2 16 premiers points de code Unicode. La bande de gris uni près du bas correspond aux moitiés de substitution utilisées par UTF-16 (la région blanche sous la bande est la zone d'utilisation privée )
Langue(s) International
Standard Norme Unicode
Classification Format de transformation Unicode , codage à largeur variable
S'étend SCU-2
Transforme / Encode ISO 10646 ( Unicode )

UTF-16 ( format de transformation Unicode 16 bits ) est un codage de caractères capable de coder tous les 1 112 064 points de code de caractères valides d'Unicode (en fait, ce nombre de points de code est dicté par la conception d'UTF-16). Le codage est de longueur variable , car les points de code sont codés avec une ou deux unités de code de 16 bits . UTF-16 est né d'un ancien codage 16 bits à largeur fixe obsolète, maintenant connu sous le nom d' UCS-2 (pour 2-byte Universal Character Set), une fois qu'il est devenu clair que plus de 2 16 (65 536) points de code étaient nécessaires.

UTF-16 est utilisé en interne par des systèmes tels que Microsoft Windows , le langage de programmation Java et JavaScript /ECMAScript. Il est également souvent utilisé pour le texte brut et pour les fichiers de données de traitement de texte sur Microsoft Windows. Il est rarement utilisé pour les fichiers sur des systèmes de type Unix. En mai 2019, Microsoft a inversé sa tendance à ne mettre l'accent que sur UTF-16 pour Unicode ; pour les applications Windows, Microsoft recommande et prend en charge UTF-8 (par exemple pour les applications Universal Windows Platform (UWP).).

UTF-16 est le seul codage Web incompatible avec ASCII , et n'a jamais gagné en popularité sur le Web, où il est utilisé par moins de 0,002 % (un peu plus de 1 millième de 1 %) des pages Web. UTF-8 , en comparaison, est utilisé par 97 % de toutes les pages Web. Le groupe de travail sur la technologie des applications hypertextes Web (WHATWG) considère l'UTF-8 « l'encodage obligatoire pour tous les [textes] » et que, pour des raisons de sécurité, les applications de navigateur ne devraient pas utiliser UTF-16.

Histoire

À la fin des années 1980, les travaux ont commencé sur le développement d'un codage uniforme pour un « jeu de caractères universel » ( UCS ) qui remplacerait les codages antérieurs propres à une langue par un système coordonné. L'objectif était d'inclure tous les caractères requis de la plupart des langues du monde, ainsi que des symboles de domaines techniques tels que les sciences, les mathématiques et la musique. L'idée originale était de remplacer les codages typiques de 256 caractères, qui nécessitaient 1 octet par caractère, par un codage utilisant 65 536 (2 16 ) valeurs, ce qui nécessiterait 2 octets (16 bits) par caractère.

Deux groupes y ont travaillé en parallèle, l' ISO/IEC JTC 1/SC 2 et le Consortium Unicode , ce dernier représentant majoritairement des fabricants d'équipements informatiques. Les deux groupes ont tenté de synchroniser leurs affectations de caractères afin que les codages en développement soient mutuellement compatibles. Le premier codage à 2 octets s'appelait à l'origine "Unicode", mais s'appelle maintenant "UCS-2".

Lorsqu'il est devenu de plus en plus clair que 2 16 caractères ne suffiraient pas, IEEE a introduit un plus grand espace de 31 bits et un codage ( UCS-4 ) qui nécessiterait 4 octets par caractère. Cela a été résisté par le Consortium Unicode , à la fois parce que 4 octets par caractère gaspillaient beaucoup de mémoire et d'espace disque, et parce que certains fabricants étaient déjà lourdement investis dans la technologie à 2 octets par caractère. Le schéma de codage UTF-16 a été développé comme un compromis et introduit avec la version 2.0 de la norme Unicode en juillet 1996. Il est entièrement spécifié dans la RFC 2781, publiée en 2000 par l' IETF .

Dans le codage UTF-16, les points de code inférieurs à 2 16 sont codés avec une seule unité de code de 16 bits égale à la valeur numérique du point de code, comme dans l'ancien UCS-2. Les points de code plus récents supérieurs ou égaux à 2 16 sont codés par une valeur composée à l'aide de deux unités de code à 16 bits. Ces deux unités de code à 16 bits sont choisies dans la plage de substitution UTF-16 0xD800-0xDFFF qui n'avait pas été précédemment affectée aux caractères. Les valeurs de cette plage ne sont pas utilisées en tant que caractères et UTF-16 ne fournit aucun moyen légal de les coder en tant que points de code individuels. Un flux UTF-16 se compose donc de points de code uniques de 16 bits en dehors de la plage de substitution pour les points de code dans le plan multilingue de base (BMP) et de paires de valeurs de 16 bits dans la plage de substitution pour les points de code au-dessus du BMP.

UTF-16 est spécifié dans les dernières versions de la norme internationale ISO/IEC 10646 et de la norme Unicode. "UCS-2 devrait maintenant être considéré comme obsolète. Il ne fait plus référence à un formulaire de codage dans 10646 ou dans la norme Unicode." Il n'est pas prévu à partir de 2021 d'étendre l'UTF-16 pour prendre en charge un plus grand nombre de points de code ou les points de code remplacés par des substituts, car cela violerait la politique de stabilité Unicode en ce qui concerne la catégorie générale ou les points de code de substitution. (Tout schéma qui reste un code d'auto-synchronisation nécessiterait l'allocation d'au moins un point de code BMP pour démarrer une séquence. La modification de l'objectif d'un point de code est interdite.)

La description

Chaque point de code Unicode est codé en une ou deux unités de code de 16 bits . La manière dont ces codes de 16 bits sont stockés sous forme d'octets dépend alors de la « endianité » du fichier texte ou du protocole de communication.

Un "caractère" peut avoir besoin d'aussi peu que deux octets à quatorze octets ou même plus pour être enregistré. Par exemple, un caractère de drapeau emoji prend 8 octets, car il est "construit à partir d'une paire de valeurs scalaires Unicode" (et ces valeurs sont en dehors du BMP et nécessitent 4 octets chacune).

U+0000 à U+D7FF et U+E000 à U+FFFF

UTF-16 et UCS-2 codent les points de code dans cette plage en tant qu'unités de code uniques de 16 bits qui sont numériquement égales aux points de code correspondants. Ces points de code dans le plan multilingue de base (BMP) sont les seuls points de code qui peuvent être représentés dans UCS-2. Depuis Unicode 9.0, certains scripts modernes non latins d'Asie, du Moyen-Orient et d'Afrique se situent en dehors de cette plage, tout comme la plupart des caractères emoji .

Points de code de U+010000 à U+10FFFF

Les points de code des autres plans (appelés plans supplémentaires ) sont codés sous la forme de deux unités de code de 16 bits appelées paire de substitution , selon le schéma suivant :

décodeur UTF-16
Meugler
Haute
DC00 DC01    ...    DFFF
D800 010000 010001 ... 0103FF
D801 010400 010401 ... 0107FF
  ?? ?? ?? ?? ??
DBFF 10FC00 10FC01 ... 10FFFF
  • 0x10000 est soustrait du point de code (U) , laissant un nombre de 20 bits (U') dans la plage de nombres hexadécimaux 0x00000–0xFFFFF. Notez qu'à ces fins, U est défini comme n'excédant pas 0x10FFFF.
  • Les dix bits de poids fort (dans la plage 0x000–0x3FF) sont ajoutés à 0xD800 pour donner la première unité de code de 16 bits ou substitut élevé (W1) , qui sera dans la plage 0xD800–0xDBFF .
  • Les dix bits de poids faible (également compris dans la plage 0x000-0x3FF) sont ajoutés à 0xDC00 pour donner la deuxième unité de code à 16 bits ou un substitut bas (W2) , qui sera compris dans la plage 0xDC00-0xDFFF .

Illustrée visuellement, la distribution de U' entre W1 et W2 ressemble à :

U' = yyyyyyyyyyxxxxxxxxxx  // U - 0x10000
W1 = 110110yyyyyyyyyy      // 0xD800 + yyyyyyyyyy
W2 = 110111xxxxxxxxxx      // 0xDC00 + xxxxxxxxxx

Le substitut haut et le substitut bas sont également appelés substituts "de tête" et "de queue", respectivement, analogues aux octets de tête et de queue de l'UTF-8.

Étant donné que les plages pour les substituts élevés ( 0xD800–0xDBFF ), les substituts faibles ( 0xDC00–0xDFFF ) et les caractères BMP valides (0x0000–0xD7FF, 0xE000–0xFFFF) sont disjoints , il n'est pas possible pour un substitut de correspondre à un caractère BMP, ou pour que deux unités de code adjacentes ressemblent à une paire de substitution légale . Cela simplifie beaucoup les recherches. Cela signifie également que l'UTF-16 se synchronise automatiquement sur des mots de 16 bits : il est possible de déterminer si une unité de code commence un caractère sans examiner les unités de code antérieures (c'est-à-dire que le type d' unité de code peut être déterminé par les plages de valeurs dans lesquelles elle chutes). L'UTF-8 partage ces avantages, mais de nombreux schémas de codage multi-octets antérieurs (tels que Shift JIS et d'autres encodages multi-octets asiatiques) ne permettaient pas une recherche sans ambiguïté et ne pouvaient être synchronisés qu'en ré-analysant à partir du début de la chaîne (UTF -16 ne s'auto-synchronise pas si un octet est perdu ou si le parcours commence à un octet aléatoire).

Étant donné que les caractères les plus couramment utilisés se trouvent tous dans le BMP, la gestion des paires de substitution n'est souvent pas testée de manière approfondie. Cela conduit à des bogues persistants et à des failles de sécurité potentielles, même dans les logiciels d'application populaires et bien évalués (par exemple CVE - 2008-2938 , CVE - 2012-2135 ).

Les plans supplémentaires contiennent des emoji , des scripts historiques, des symboles moins utilisés, des idéogrammes chinois moins utilisés, etc. Étant donné que le codage des plans supplémentaires contient 20 bits significatifs (10 sur 16 bits dans chacun des substituts haut et bas ), 2 20 points de code peuvent être codé, divisé en 16 plans de 2 16 points de code chacun. Y compris l'avion multilingue de base géré séparément, il y a un total de 17 avions.

U+D800 à U+DFFF

La norme Unicode réserve en permanence ces valeurs de point de code pour l'encodage UTF-16 des substituts haut et bas, et un caractère ne leur sera jamais attribué, il ne devrait donc y avoir aucune raison de les encoder. La norme officielle Unicode indique qu'aucun formulaire UTF, y compris UTF-16, ne peut coder ces points de code.

Cependant, UCS-2, UTF-8 et UTF-32 peuvent coder ces points de code de manière triviale et évidente, et une grande quantité de logiciels le fait, même si la norme stipule que de tels arrangements doivent être traités comme des erreurs de codage.

Il est possible d'encoder sans ambiguïté un substitut non apparié (un point de code de substitution élevé non suivi d'un point faible, ou un point faible non précédé d'un point élevé) au format UTF-16 en utilisant une unité de code égale au point de code . Le résultat n'est pas un UTF-16 valide, mais la majorité des implémentations d'encodeur et de décodeur UTF-16 le font alors lors de la traduction entre les codages. Windows autorise des substituts non appariés dans les noms de fichiers et à d'autres endroits, ce qui signifie généralement qu'ils doivent être pris en charge par un logiciel malgré leur exclusion de la norme Unicode.

Exemples

Pour coder U+10437 (𐐷) en UTF-16 :

  • Soustrayez 0x10000 du point de code, en laissant 0x0437.
  • Pour le substitut élevé, décalez vers la droite de 10 (divisez par 0x400), puis ajoutez 0xD800, ce qui donne 0x0001 + 0xD800 = 0xD801.
  • Pour le substitut inférieur, prenez les 10 bits inférieurs (reste de la division par 0x400), puis ajoutez 0xDC00, ce qui donne 0x0037 + 0xDC00 = 0xDC37.

Pour décoder U+10437 (𐐷) à partir d'UTF-16 :

  • Prenez le substitut élevé (0xD801) et soustrayez 0xD800, puis multipliez par 0x400, ce qui donne 0x0001 × 0x400 = 0x0400.
  • Prenez le substitut faible (0xDC37) et soustrayez 0xDC00, ce qui donne 0x37.
  • Additionnez ces deux résultats (0x0437) et ajoutez enfin 0x10000 pour obtenir le point de code UTF-32 décodé final, 0x10437.

Le tableau suivant résume cette conversion, ainsi que d'autres. Les couleurs indiquent comment les bits du point de code sont répartis entre les octets UTF-16. Les bits supplémentaires ajoutés par le processus de codage UTF-16 sont affichés en noir.

Personnage Point de code binaire UTF-16 binaire
Unités de code hexadécimal UTF-16
Octets
hexadécimaux UTF-16BE
Octets
hexadécimaux UTF-16LE
$ U+0024 0000 0000 0010 0100 0000 0000 0010 0100 0024 00 24 24 00
U+20AC 0010 0000 1010 1100 0010 0000 1010 1100 20AC 20 AC AC 20
?? U+10437 0001 0000 0100 0011 0111 1101 1000 0000 0001 1101 1100 0011 0111 D801 DC37 D8 01 DC 37 01 D8 37 DC
?? U+24B62 0010 0100 1011 0110 0010 1101 1000 0101 0010 1101 1111 0110 0010 D852 DF62 D8 52 DF 62 52 D8 62 DF

Schémas de codage dans l'ordre des octets

UTF-16 et UCS-2 produisent une séquence d'unités de code de 16 bits. Étant donné que la plupart des protocoles de communication et de stockage sont définis pour des octets, et que chaque unité prend donc deux octets de 8 bits, l'ordre des octets peut dépendre de l' endianness (ordre des octets) de l'architecture informatique.

Pour aider à reconnaître l'ordre des octets des unités de code, UTF-16 permet à une marque d'ordre d'octet (BOM), un point de code avec la valeur U+FEFF, de précéder la première valeur codée réelle. (U+FEFF est le caractère invisible de l' espace insécable de largeur zéro /ZWNBSP.) Si l'architecture endian du décodeur correspond à celle du codeur, le décodeur détecte la valeur 0xFEFF, mais un décodeur endian opposé interprète la nomenclature comme le valeur non-caractère U+FFFE réservée à cet effet. Ce résultat incorrect fournit une indication pour effectuer un échange d'octets pour les valeurs restantes.

Si la nomenclature est manquante, la RFC 2781 recommande que l'encodage big-endian soit supposé. En pratique, en raison de l'utilisation par défaut de l'ordre little-endian par Windows, de nombreuses applications supposent un codage little-endian. Il est également fiable de détecter le caractère endian en recherchant des octets nuls, en supposant que les caractères inférieurs à U+0100 sont très courants. Si plus d'octets pairs (à partir de 0) sont nuls, alors il s'agit de gros-boutiste.

La norme permet également d'indiquer explicitement l'ordre des octets en spécifiant UTF-16BE ou UTF-16LE comme type de codage. Lorsque l'ordre des octets est spécifié explicitement de cette manière, une nomenclature n'est spécifiquement pas censée être préfixée au texte, et un U+FEFF au début doit être traité comme un caractère ZWNBSP. La plupart des applications ignorent une nomenclature dans tous les cas malgré cette règle.

Pour les protocoles Internet , l' IANA a approuvé « UTF-16 », « UTF-16BE » et « UTF-16LE » comme noms pour ces encodages (les noms sont insensibles à la casse). Les alias UTF_16 ou UTF16 peuvent être significatifs dans certains langages de programmation ou applications logicielles, mais ce ne sont pas des noms standard dans les protocoles Internet.

Des désignations similaires, UCS-2BE et UCS-2LE , sont utilisées pour montrer les versions d' UCS-2 .

Usage

UTF-16 est utilisé pour le texte dans l'API du système d'exploitation de toutes les versions actuellement prises en charge de Microsoft Windows (et y compris au moins toutes depuis Windows CE / 2000 / XP / 2003 / Vista / 7 ) y compris Windows 10 . Sous Windows XP, aucun point de code au-dessus de U+FFFF n'est inclus dans les polices fournies avec Windows pour les langues européennes. Les systèmes Windows NT plus anciens (avant Windows 2000) ne prennent en charge que UCS-2. Les fichiers et les données réseau ont tendance à être un mélange d'encodages d'octets UTF-16, UTF-8 et hérités.

Bien qu'il y ait eu une certaine prise en charge UTF-8 pour même Windows XP, elle a été améliorée (en particulier la possibilité de nommer un fichier en utilisant UTF-8) dans Windows 10 Insider build 17035 et la mise à jour d'avril 2018, et à partir de mai 2019, Microsoft recommande un logiciel utilisez-le à la place de UTF-16.

Le système d'exploitation IBM i désigne le CCSID ( page de codes ) 13488 pour le codage UCS-2 et le CCSID 1200 pour le codage UTF-16, bien que le système les traite tous les deux comme UTF-16.

UTF-16 est utilisé par les systèmes d'exploitation Qualcomm BREW ; les environnements .NET ; et la boîte à outils de widgets graphiques multiplateformes Qt .

Le système d'exploitation Symbian utilisé dans les combinés Nokia S60 et les combinés Sony Ericsson UIQ utilise UCS-2. Les téléphones iPhone utilisent UTF-16 pour le service de messages courts au lieu de UCS-2 décrit dans les normes 3GPP TS 23.038 ( GSM ) et IS-637 ( CDMA ).

Le système de fichiers Joliet , utilisé dans les supports CD-ROM , code les noms de fichiers à l'aide de l'UCS-2BE (jusqu'à soixante-quatre caractères Unicode par nom de fichier).

L' environnement du langage Python n'utilise officiellement UCS-2 en interne que depuis la version 2.0, mais le décodeur UTF-8 vers "Unicode" produit un UTF-16 correct. Depuis Python 2.2, les versions "larges" d'Unicode sont prises en charge et utilisent plutôt UTF-32 ; ceux-ci sont principalement utilisés sur Linux. Python 3.3 n'utilise plus jamais UTF-16, mais un codage qui donne la représentation la plus compacte pour la chaîne donnée est choisi parmi ASCII/Latin-1, UCS-2 et UTF-32.

Java utilisait à l'origine UCS-2 et a ajouté la prise en charge des caractères supplémentaires UTF-16 dans J2SE 5.0 .

JavaScript peut utiliser UCS-2 ou UTF-16. Depuis ES2015, des méthodes de chaîne et des indicateurs d'expression régulière ont été ajoutés au langage qui permettent de gérer les chaînes d'un point de vue indépendant de l'encodage.

Dans de nombreuses langues, les chaînes entre guillemets ont besoin d'une nouvelle syntaxe pour citer les caractères non BMP, car la "\uXXXX"syntaxe de style C se limite explicitement à 4 chiffres hexadécimaux. Les exemples suivants illustrent la syntaxe du caractère non BMP « 𝄞 » (U+1D11E, SYMBOLE MUSICAL G CLEF). Le plus courant (utilisé par C++ , C# , D et plusieurs autres langages) consiste à utiliser un « U » majuscule avec 8 chiffres hexadécimaux tels que "\U0001D11E". Dans les expressions régulières Java 7, ICU et Perl, la syntaxe "\x{1D11E}"doit être utilisée ; de même, dans ECMAScript 2015 (JavaScript), le format d'échappement est "\u{1D11E}". Dans de nombreux autres cas (comme Java en dehors des expressions régulières), le seul moyen d'obtenir des caractères non BMP est d'entrer les moitiés de substitution individuellement, par exemple : "\uD834\uDD1E"pour U+1D11E.

Les implémentations de chaînes basées sur UTF-16 définissent généralement les longueurs de la chaîne et permettent l'indexation en termes d' unités de code 16 bits , et non en termes de points de code. Ni les points de code ni les unités de code ne correspondent à quoi que ce soit qu'un utilisateur final puisse reconnaître comme un « caractère » ; les éléments que les utilisateurs identifient en tant que caractères peuvent en général consister en un point de code de base et une séquence de caractères combinés (ou peuvent être une séquence de points de code d'un autre type, par exemple Hangul joignant jamos) - Unicode fait référence à cette construction en tant que graphème cluster  - et en tant que tel, les applications traitant des chaînes Unicode, quel que soit l'encodage, doivent faire face au fait que cela limite leur capacité à diviser et combiner arbitrairement des chaînes.

UCS-2 est également supporté par le langage PHP et MySQL.

Swift , version 5, le langage d'application préféré d'Apple, est passé d'UTF-16 à UTF-8 comme encodage préféré.

Voir également

Remarques

Les références

Liens externes