152 votes

Différence entre UTF-8 et UTF-16 ?

Différence entre UTF-8 et UTF-16 ? Pourquoi en avons-nous besoin ?

MessageDigest md = MessageDigest.getInstance("SHA-256");
String text = "This is some text";

md.update(text.getBytes("UTF-8")); // Change this to "UTF-16" if needed
byte[] digest = md.digest();

4 votes

Jon skeet a un bon article sur l'encodage.... csharpindepth.com/Articles/General/Unicode.aspx

313voto

Sergey Tachenov Points 8123

Je crois qu'il y a beaucoup de bons articles à ce sujet sur le Web, mais voici un bref résumé.

UTF-8 et UTF-16 sont tous deux des codages à longueur variable. Toutefois, en UTF-8, un caractère peut occuper un minimum de 8 bits, tandis qu'en UTF-16, la longueur des caractères commence à 16 bits.

Principaux pros de l'UTF-8 :

  • Les caractères ASCII de base, tels que les chiffres, les caractères latins sans accents, etc., occupent un octet qui est identique à la représentation US-ASCII. De cette façon, toutes les chaînes US-ASCII deviennent des UTF-8 valides, ce qui offre une compatibilité descendante décente dans de nombreux cas.
  • Pas d'octets nuls, ce qui permet d'utiliser des chaînes de caractères à terminaison nulle, ce qui introduit également une grande compatibilité ascendante.
  • UTF-8 est indépendant de l'ordre des octets, vous n'avez donc pas à vous soucier du problème Big Endian / Little Endian.

Principale contre UTF-8 :

  • De nombreux caractères courants ont une longueur différente, ce qui ralentit terriblement l'indexation par codepoint et le calcul du nombre de codepoints.
  • Même si l'ordre des octets n'a pas d'importance, il arrive que l'UTF-8 comporte encore des BOM (byte order mark) qui servent à notifier que le texte est codé en UTF-8, et qui rompent également la compatibilité avec les logiciels ASCII même si le texte ne contient que des caractères ASCII. Les logiciels Microsoft (comme Notepad) aiment particulièrement ajouter des BOM à UTF-8.

Principaux pros UTF-16 :

  • Les caractères BMP (basic multilingual plane), dont le latin, le cyrillique, la plupart des caractères chinois (la RPC a rendu obligatoire la prise en charge de certains points de code non BMP), la plupart des caractères japonais peuvent être représentés avec 2 octets. Cela accélère l'indexation et le calcul du nombre de points de code dans le cas où le texte n'a pas d'octets. no contiennent des caractères supplémentaires.
  • Même si le texte comporte des caractères supplémentaires, ils sont toujours représentés par des paires de valeurs de 16 bits, ce qui signifie que la longueur totale est toujours divisible par deux et permet d'utiliser des caractères de 16 bits. char comme composant primitif de la chaîne.

Principales cons. UTF-16

  • Beaucoup d'octets nuls dans les chaînes US-ASCII, ce qui signifie qu'il n'y a pas de chaînes à terminaison nulle et beaucoup de mémoire gaspillée.
  • Son utilisation en tant qu'encodage à longueur fixe "fonctionne généralement" dans de nombreux scénarios courants (notamment aux États-Unis, dans l'Union européenne, dans les pays dotés d'un alphabet cyrillique, en Israël, dans les pays arabes, en Iran et dans bien d'autres pays), ce qui conduit souvent à un support défectueux dans les autres cas. Cela signifie que les programmeurs doivent être conscients des paires de substitution et les gérer correctement dans les cas où cela est important !
  • La longueur étant variable, le comptage ou l'indexation des points de code est coûteux, mais moins que l'UTF-8.

En général, UTF-16 est meilleur pour la représentation en mémoire parce que BE/LE n'est pas pertinent ici (utilisez simplement l'ordre natif) et l'indexation est plus rapide (n'oubliez pas de gérer correctement les paires de substituts). UTF-8, d'autre part, est extrêmement bon pour les fichiers texte et les protocoles réseau parce qu'il n'y a pas de problème de BE/LE et la terminaison nulle est souvent utile, ainsi que la compatibilité ASCII.

3 votes

Il ne manque que la partie BE/LE sur l'UTF16 :) UTF-8 a un autre inconvénient, il peut générer une sortie plus longue que UTF16.

4 votes

Oui, j'ai oublié le BE/LE. Mais ce n'est pas un gros problème, surtout pour une utilisation en mémoire. UTF-8 ne génère une sortie plus longue que si des caractères de trois octets sont impliqués, ce qui signifie principalement le chinois et le japonais. D'un autre côté, si le texte contient beaucoup de caractères US-ASCII, il peut générer une sortie plus courte, donc le fait que ce soit un inconvénient ou non dépend d'une situation particulière.

0 votes

Je n'ai même pas pensé à mentionner l'avantage immédiat de l'utf-8, une longueur plus courte. A propos de la sortie plus longue de l'utf-8, c'était 'may' pour une raison, pourtant si la cible est en Extrême-Orient, l'encodage par défaut devrait être l'utf-16. Comme pour l'exemple md.update(text.getBytes("UTF-8")) ; l'encodage n'a pas d'importance puisque le hachage est stable dans les deux sens.

20voto

Jon Skeet Points 692016

Il s'agit simplement de schémas différents pour représenter les caractères Unicode.

Les deux sont de longueur variable - l'UTF-16 utilise 2 octets pour tous les caractères du plan multilingue de base (BMP) qui contient la plupart des caractères d'usage courant.

UTF-8 utilise entre 1 et 3 octets pour les caractères dans le BMP, jusqu'à 4 pour les caractères dans la gamme Unicode actuelle de U+0000 à U+1FFFFF, et est extensible jusqu'à U+7FFFFFFF si cela devient nécessaire... mais notamment tous les caractères ASCII sont représentés dans un seul octet chacun.

Dans le cadre d'un résumé de message, le choix de l'une ou l'autre de ces options n'a pas d'importance, tant que tous ceux qui tentent de recréer le résumé utilisent la même option.

Voir cette page pour en savoir plus sur UTF-8 et Unicode.

(Notez que tous les caractères Java sont des points de code UTF-16 dans le BMP ; pour représenter les caractères supérieurs à U+FFFF, vous devez utiliser des paires de substitution en Java).

11voto

Basil Bourque Points 8938

Sécurité : Utilisez uniquement UTF-8

Différence entre UTF-8 et UTF-16 ? Pourquoi en avons-nous besoin ?

Il y a eu au moins deux vulnérabilités de sécurité dans des implémentations de UTF-16 . Voir Wikipedia pour plus de détails .

WHATWG y W3C tienen maintenant déclaré que seulement UTF-8 est destiné à être utilisé sur le Web.

Les problèmes [de sécurité] décrits ici disparaissent lorsqu'on utilise exclusivement UTF-8, ce qui est l'une des nombreuses raisons pour lesquelles cet encodage est désormais obligatoire pour tout.

D'autres groupes disent la même chose.

Ainsi, si l'UTF-16 peut continuer à être utilisé en interne par certains systèmes tels que Java et Windows, le peu d'utilisation de l'UTF-16 que vous avez pu voir dans le passé pour les fichiers de données, l'échange de données et autres, va probablement disparaître complètement.

4voto

bestsss Points 6403

Ceci n'a rien à voir avec UTF-8/16 (en général, bien qu'il convertisse en UTF16 et que la partie BE/LE puisse être définie en une seule ligne), mais voici la façon la plus rapide de convertir String en byte[]. Par exemple : bon exactement pour le cas fourni (code de hachage). String.getBytes(enc) est relativement lent.

static byte[] toBytes(String s){
        byte[] b=new byte[s.length()*2];
        ByteBuffer.wrap(b).asCharBuffer().put(s);
        return b;
    }

1voto

Abdullah Jibaly Points 14269

À l'origine, il s'agit du nombre d'octets (java utilise utf-16) par caractère. utf-8 correspond à 1 octet, utf-16 à 2 octets. La raison pour laquelle vous devez savoir cela est que certains fichiers texte peuvent être encodés en utf-8.

Ce lien devrait vous aider :

http://java.sun.com/javase/technologies/core/basic/intl/faq.jsp

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X