Les problèmes de jeux de caractères sont déroutants et compliqués en eux-mêmes, mais en plus de cela, vous devez vous souvenir des noms exacts de vos jeux de caractères. C'est ça "utf8"
? Ou "utf-8"
? Ou peut "UTF-8"
- être ? Lorsque vous recherchez des exemples de code sur Internet, vous verrez tout ce qui précède. Pourquoi ne pas simplement leur faire des constantes nommées et les utiliser Charset.UTF8
?
211
MessageDigest#getInstance()
.Réponses:
La réponse simple à la question posée est que les chaînes de caractères disponibles varient d'une plateforme à l'autre.
Cependant, il y en a six qui doivent être présents, donc des constantes auraient pu être faites depuis longtemps. Je ne sais pas pourquoi ils ne l'étaient pas.
JDK 1.4 a fait une grande chose en introduisant le type Charset. À ce stade, ils n'auraient plus voulu fournir de constantes String, car l'objectif est d'amener tout le monde à utiliser les instances de Charset. Alors pourquoi ne pas fournir les six constantes Charset standard? J'ai demandé à Martin Buchholz car il se trouve juste à côté de moi, et il a dit qu'il n'y avait pas vraiment de bonne raison, sauf qu'à l'époque, les choses étaient encore à moitié cuites - trop peu d'API JDK avaient été modernisées pour accepter Charset, et parmi ceux qui l'étaient, les surcharges de Charset se sont généralement comportées légèrement moins bien.
Il est triste que ce soit seulement dans JDK 1.6 qu'ils aient finalement fini de tout équiper avec des surcharges Charset. Et que cette situation de performances en arrière existe toujours (la raison pour laquelle c'est incroyablement bizarre et je ne peux pas l'expliquer, mais est liée à la sécurité!).
Pour faire court - définissez simplement vos propres constantes, ou utilisez la classe Charsets de Guava à laquelle Tony le Poney était lié (bien que cette bibliothèque ne soit pas encore réellement publiée).
Mise à jour: une
StandardCharsets
classe est en JDK 7.la source
String(byte bytes[], int offset, int length, Charset charset)
est mis en œuvre. En fait, la performance atteinte n'est pas du tout triviale lors de la création d'une petite chaîne à partir d'un grand octet [].Deux ans plus tard, et Java 7 de les StandardCharsets définit maintenant des constantes pour les 6 jeux de caractères standard.
Si vous êtes bloqué sur Java 5/6, vous pouvez utiliser les constantes Charsets de Guava , comme suggéré par Kevin Bourrillion et Jon Skeet.
la source
Je dirais que nous pouvons faire beaucoup mieux que cela ... pourquoi les jeux de caractères dont la disponibilité est garantie ne sont-ils pas directement accessibles?
Charset.UTF8
devrait être une référence à laCharset
, pas le nom sous forme de chaîne. De cette façon, nous n'aurions pas à gérerUnsupportedEncodingException
partout.Remarquez, je pense également que .NET a choisi une meilleure stratégie en optant par défaut pour UTF-8 partout. Il a ensuite bousillé en nommant simplement la propriété de codage "défaut du système d'exploitation"
Encoding.Default
- qui n'est pas la valeur par défaut dans .NET lui-même :(Revenons à propos de la prise en charge des jeux de caractères Java - pourquoi n'y a-t-il pas de constructeur pour
FileWriter
/FileReader
qui prend unCharset
? Fondamentalement, ce sont des classes presque inutiles en raison de cette restriction - vous avez presque toujours besoin d'unInputStreamReader
autour d'unFileInputStream
ou de l'équivalent pour la sortie :(Infirmière, infirmière - où est mon médicament?
EDIT: Il me vient à l'esprit que cela n'a pas vraiment répondu à la question. La vraie réponse est vraisemblablement soit "personne impliqué n'y a pensé" ou "quelqu'un impliqué a pensé que c'était une mauvaise idée". Je suggérerais fortement que les classes utilitaires internes fournissant les noms ou les jeux de caractères évitent la duplication autour de la base de code ... Ou vous pouvez simplement utiliser celui que nous avons utilisé chez Google lorsque cette réponse a été écrite pour la première fois . (Notez que depuis Java 7, vous utiliseriez simplement à la
StandardCharsets
place.)la source
Dans Java 1.7
import java.nio.charset.StandardCharsets
ex:
StandardCharsets.UTF_8
StandardCharsets.US_ASCII
la source
L'état actuel de l'API d'encodage laisse à désirer. Certaines parties de l'API Java 6 n'acceptent
Charset
en place d'une chaîne (enlogging
,dom.ls
,PrintStream
, il peut y avoir d' autres). Cela n'aide pas que les encodages soient supposés avoir des noms canoniques différents pour différentes parties de la bibliothèque standard.Je peux comprendre comment les choses sont arrivées là où elles sont; Je ne suis pas sûr d'avoir des idées brillantes sur la façon de les corriger.
En aparté...
Vous pouvez rechercher les noms de l'implémentation de Java 6 de Sun ici .
Pour UTF-8, les valeurs canoniques sont
"UTF-8"
pourjava.nio
et"UTF8"
pourjava.lang
etjava.io
. Les seuls encodages que la spécification nécessite un JRE pour prendre en charge sont: US-ASCII; ISO-8859-1; UTF-8; UTF-16BE; UTF-16LE; UTF-16 .la source
J'ai défini il y a longtemps une classe utilitaire avec les constantes UTF_8, ISO_8859_1 et US_ASCII Charset.
En outre, il y a quelque temps longtemps (2 ans et plus ) je l' ai fait un simple test de performance entre
new String( byte[], Charset )
etnew String( byte[], String charset_name )
et a découvert que cette dernière mise en œuvre est FORTEMENT plus rapide. Si vous jetez un œil sous le capot au code source, vous verrez qu'ils suivent en effet un chemin tout à fait différent.Pour cette raison, j'ai inclus un utilitaire dans la même classe
Pourquoi le constructeur String (byte [], Charset) ne fait pas la même chose, me bat.
la source
Charset
besoin n'a pas besoin d'être enregistré, donc l'exception peut se produire. IIRC, il y a eu quelques changements dans JDK7 pour le rendre plus rapide pour lesCharset
implémentations connues (éliminer la copie supplémentaire).