web-dev-qa-db-fra.com

Qu'est-ce qu'une "paire de substitution" en Java?

Je lisais la documentation de StringBuffer, en particulier la méthode reverse () . Cette documentation mentionne quelque chose à propos de paires de substitution . Qu'est-ce qu'une paire de substitution dans ce contexte? Et quels sont bas et hauts substituts?

135
Raymond

Le terme "paire de substitution" désigne un moyen de coder des caractères Unicode avec des points de code élevés dans le schéma de codage UTF-16.

Dans le codage de caractères Unicode, les caractères sont associés à des valeurs comprises entre 0x0 et 0x10FFFF.

En interne, Java utilise le schéma de codage UTF-16 pour stocker les chaînes de texte Unicode. En UTF-16, les unités de code 16 bits (deux octets) sont utilisées. Étant donné que 16 bits ne peuvent contenir que plage de caractères allant de 0x0 à 0xFFFF, une complexité supplémentaire est utilisée pour stocker les valeurs supérieures à cette plage (0x10000 à 0x10FFFF), à l’aide de paires d’unités de code appelées substituts.

Les unités de code de substitution se situent dans deux plages appelées "mères de substitution" et "mères de substitution", selon qu'elles sont autorisées au début ou à la fin de la séquence de deux unités de code.

115

Early Java représentaient des caractères Unicode utilisant le type de données 16 caractères. Cette conception était logique à l'époque, car tous les caractères Unicode avaient des valeurs inférieures à 65 535 (0xFFFF) et pouvaient être représentés sous 16 caractères. Toutefois, plus tard, Unicode a augmenté la valeur maximale à 1 114 111 (0x10FFFF). Les valeurs 16 bits étant trop petites pour représenter tous les caractères Unicode de la version Unicode 3.1, des valeurs 32 bits - appelées points de code - ont été adoptées pour la Schéma de codage UTF-32, mais les valeurs 16 bits sont préférables aux valeurs 32 bits pour une utilisation efficace de la mémoire, aussi Unicode a-t-il introduit une nouvelle conception permettant de continuer à utiliser les valeurs 16 bits. Cette conception, adoptée dans le format UTF-16 schéma de codage, attribue 1 024 valeurs à des substituts 16 bits (dans la plage U + D800 à U + DBFF) et 1 024 autres valeurs à des substituts 16 bits (dans la plage U + DC00 à U + DFFF). valeur de substitution élevée suivie d'une valeur de substitution faible - une paire de substitution - pour représenter (le produit de 1 024 et 1 024) 1,0 48 576 (0x100000) valeurs comprises entre 65 536 (0x10000) et 1 114 111 (0x10FFFF).

44
ibrahem shabban

Ce que dit la documentation, c'est que des chaînes UTF-16 non valides peuvent devenir valides après l'appel de la méthode reverse, car elles pourraient être les inverses de chaînes valides. Une paire de substitution (discutée ici ) est une paire de valeurs de 16 bits en UTF-16 qui codent un seul point de code Unicode; les substituts bas et haut sont les deux moitiés de ce codage.

22

Ajout de quelques informations supplémentaires aux réponses ci-dessus de this post

Testé en Java-12, devrait fonctionner dans toutes les Java ci-dessus 5.

Comme mentionné ici: https://stackoverflow.com/a/47505451/2987755 ,
le caractère (dont le code Unicode est supérieur à U + FFFF) est représenté par une paire de substitution, ce qui Java est stocké sous la forme d'une paire de valeurs de caractère, c'est-à-dire que le caractère Unicode unique est représenté par deux adjacent Java caractères.
Comme on peut le voir dans l'exemple suivant.
1. Longueur:

"????".length()  //2, Expectations was it should return 1

"????".codePointCount(0,"????".length())  //1, To get number of Unicode character in Java String  

2. égalité:
Représente "????" to String en utilisant Unicode \ud83c\udf09 comme ci-dessous et vérifiez l’égalité.

"????".equals("\ud83c\udf09") // true

Java ne supporte pas UTF-32

"????".equals("\u1F309") // false  

3. Vous pouvez convertir un caractère Unicode en Java String

"????".equals(new String(Character.toChars(0x0001F309))) //true

4. String.substring () ne prend pas en compte les caractères supplémentaires

"????????".substring(0,1) //"?"
"????????".substring(0,2) //"????"
"????????".substring(0,4) //"????????"

Pour résoudre ce problème, nous pouvons utiliser String.offsetByCodePoints(int index, int codePointOffset)

"????????".substring(0,"????????".offsetByCodePoints(0,1) // "????"
"????????".substring(2,"????????".offsetByCodePoints(1,2)) // "????"

5. Itération de chaîne Unicode avec BreakIterator
6. Tri de chaînes avec Unicode Java.text.Collator
7. Les caractères en majuscules et minuscules ne doivent pas être utilisés. Utilisez plutôt les majuscules et minuscules des paramètres régionaux.
8. Character.isLetter(char ch) ne supporte pas, mieux utilisé Character.isLetter(int codePoint), pour chaque méthode methodName(char ch) de la classe Character, il y aura un type de methodName(int codePoint) pouvant gérer caractères supplémentaires.
9. Spécifiez le jeu de caractères dans String.getBytes(), en convertissant d'octets en chaîne, InputStreamReader, OutputStreamWriter.

Ref:
https://coolsymbol.com/emojis/emoji-for-copy-and-paste.html#objects
https://www.online-toolz.com/tools/text-unicode-entities-convertor.php
https://www.ibm.com/developerworks/library/j-unicode/index.html
https://www.Oracle.com/technetwork/articles/javaee/supplementary-142654.html

Plus d'informations sur l'exemple image1image2
Autres termes à explorer: Normalisation , BiDi

7
dkb

Les paires de substitution renvoient à la manière dont UTF-16 code certains caractères, voir http://en.wikipedia.org/wiki/UTF-16/UCS-2#Code_points_U.2B10000..U.2B10FFFF

6
dfb

Une paire de substitution est constituée de deux "unités de code" dans UTF-16 qui constituent un "point de code". La documentation de Java indique que ces "points de code" seront toujours valides, avec leurs "unités de code" ordonnées correctement, après l'inverse. Elle indique en outre que deux unités de code de substitution non appariées peuvent être inversées et formez une paire de substitution valide, ce qui signifie que s’il existe des unités de code non appariées, il est possible que l’inverse de l’inverse ne soit pas le même!

Notez cependant que la documentation ne dit rien sur Graphemes - qui sont plusieurs points de code combinés. Ce qui signifie que e et l'accent qui l'accompagne peuvent toujours être modifiés, plaçant ainsi l'accent avant le e. Ce qui signifie que s'il y a une autre voyelle avant le e, elle peut obtenir l'accent qui était sur le e.

Beurk!

3
Gerard ONeill

Petite préface

  • Unicode représente les points de code. Chaque point de code peut être codé en blocs de 8, 16, ou 32 bits selon la norme Unicode.
  • Avant la version 3.1, on utilisait principalement l'encodage à 8 bits, appelé UTF-8, et l'encodage à 16 bits, appelé UCS-2 ou "Jeu ​​de caractères universel codé sur 2 octets". UTF-8 code les points Unicode en une séquence de blocs de 1 octet, alors que UCS-2 prend toujours 2 octets:

    A = 41 - un bloc de 8 bits avec UTF-8
    A = 0041 - un bloc de 16 bits avec UCS-2
    Ω = CE A9 - deux blocs de 8 bits avec UTF-8
    Ω = 03A9 - un bloc de 16 bits avec UCS-2

Problème

Le consortium a estimé que 16 bits seraient suffisants pour couvrir tout langage lisible par l'homme, ce qui donne 2 ^ 16 = 65536 valeurs de code possibles. Cela était vrai pour le plan 0, également appelé plan BPM ou plan multilingue de base, qui comprend aujourd'hui 55 445 des 65 536 points de code. Le BPM couvre presque toutes les langues humaines du monde, y compris les symboles chinois-japonais-coréen (CJK).

Le temps a passé et de nouveaux jeux de caractères asiatiques ont été ajoutés, les symboles chinois ont pris plus de 70 000 points. Maintenant, il y a même points Emoji dans le cadre de la norme ????. De nouveaux 16 "supplémentaires" avions ont été ajoutés. La salle UCS-2 n'était pas suffisante pour couvrir quoi que ce soit plus grand que Plane-0.

Décision Unicode

  1. Limiter Unicode aux 17 plans × 65 536 caractères par plan = 1 114 112 points maximum.
  2. Le format UTF-32 actuel, appelé UCS-4, peut contenir 32 bits pour chaque point de code et couvrir tous les plans.
  3. Continuez à utiliser le codage dynamique UTF-8, limitez le codage UTF-8 à 4 octets maximum pour chaque point de code, c’est-à-dire de 1 à 4 octets par point.
  4. Obsolète UCS-2
  5. Créez le format UTF-16 basé sur UCS-2. Rendre UTF-16 dynamique, il faut donc 2 octets ou 4 octets par point. Attribuez 1024 points U + D800 – U + DBFF, appelés valeurs de substitution élevées, à UTF-16; attribuez 1024 symboles U + DC00 – U + DFFF, appelés valeurs de substitution faibles, à UTF-16.

    Avec ces modifications, le BPM est recouvert d’un bloc de 16 bits en UTF-16, tandis que tous les "caractères supplémentaires" sont couverts de paires de substitution présentant 2 blocs par 16 bits chacun, totalement 1024x1024 = 1 048 576 points.

    Un substitut élevé précède un substitut bas. Tout écart par rapport à cette règle est considéré comme un mauvais encodage. Par exemple, un substitut sans paire est incorrect, un substitut bas devant un substitut élevé est incorrect.

    ????, 'MUSICAL SYMBOL G CLEF', est codé en UTF-16 comme une paire de substituts 0xD834 0xDD1E (2 par 2 octets),
    dans UTF-8 sous la forme 0xF0 0x9D 0x84 0x9E (octet sur 4),
    en UTF-32 sous la forme 0x0001D11E (1 sur 4 octets).

Situation actuelle

  • Bien que, conformément à la norme, les substituts ne soient spécifiquement affectés qu'à UTF-16, historiquement, certaines applications Windows et Java) utilisaient des points UTF-8 et UCS-2 réservés à présent pour la plage des substituts.
    Pour prendre en charge les applications héritées avec des codages UTF-8/UTF-16 incorrects, un nouveau standard WTF-8 , Format de transformation wobbly, a été créé. Il prend en charge des points de substitution arbitraires, tels qu'un substitut non apparié ou une séquence incorrecte. Aujourd'hui, certains produits ne sont pas conformes à la norme et traitent l'UTF-8 en tant que WTF-8.
  • La solution de substitution a ouvert de nombreux problèmes de sécurité lors de la conversion entre différents codages, la plupart d’entre eux ont été bien gérés.

De nombreux détails historiques ont été supprimés pour suivre le sujet.
La dernière norme Unicode est disponible à l’adresse suivante: http://www.unicode.org/versions/latest

0
Artru