Pourquoi les noms de jeux de caractères ne sont-ils pas des constantes?

Les problèmes de jeu de caractères sont déroutants et compliqués par eux-mêmes, mais en plus, vous devez vous souvenir des noms exacts de vos jeux de caractères. Est-ce "utf8" ? Ou "utf-8" ? Ou peut "UTF-8" être "UTF-8" ? Lorsque vous recherchez des exemples de code sur Internet, vous verrez tout ce qui précède. Pourquoi ne pas simplement les nommer constantes et utiliser Charset.UTF8 ?

La réponse simple à la question posée est que les chaînes de caractères disponibles varient d’une plate-forme à l’autre.

Cependant, il y en a six qui sont nécessaires pour être présents, de sorte que des constantes auraient pu être faites depuis longtemps. Je ne sais pas pourquoi ils ne l’étaient pas.

JDK 1.4 a fait du bon travail en introduisant le type Charset. À ce stade, ils n’auraient plus voulu fournir de constantes de type Ssortingng, le but étant d’obtenir que tout le monde utilise des instances de Charset. Alors, pourquoi ne pas fournir les six constantes Charset standard, alors? J’ai demandé à Martin Buchholz, car il se trouve juste à côté de moi, et il a dit qu’il n’y avait pas une très bonne raison, sauf qu’à l’époque, les choses étaient encore à moitié préparées – trop peu d’API JDK avaient été adaptées à accepter Charset, et de ceux qui étaient, le Charset surcharges généralement effectué légèrement pire.

Il est sortingste que ce ne soit que dans JDK 1.6 qu’ils aient finalement tout équipé avec des surcharges Charset. Et que cette performance en arrière existe toujours (la raison est incroyablement étrange et je ne peux pas l’expliquer, mais est liée à la sécurité!).

Longue histoire courte – définissez simplement vos propres constantes, ou utilisez la classe Charsets de Guava à laquelle Tony the Pony a lié (bien que cette bibliothèque ne soit pas vraiment vraiment sortie).

Update: une classe StandardCharsets est dans JDK 7.

Deux ans plus tard, le jeu StandardCharsets de Java 7 définit désormais les constantes des 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.

Je dirais que nous pouvons faire beaucoup mieux que cela … pourquoi les jeux de caractères garantis ne sont-ils pas accessibles directement? Charset.UTF8 devrait être une référence au Charset , pas le nom sous forme de chaîne. De cette façon, nous n’aurions pas à gérer une UnsupportedEncodingException partout.

Attention, je pense aussi que .NET a choisi une meilleure stratégie en utilisant par défaut UTF-8 partout. Il a ensuite bousillé en nommant la propriété de codage “default system” simplement Encoding.Default – qui n’est pas la valeur par défaut dans .NET lui-même 🙁

De nouveau à propos du support des jeux de caractères Java – pourquoi n’y a-t-il pas un constructeur pour FileWriter / FileReader qui prend un jeu de Charset ? Fondamentalement, ce sont des classes presque inutiles à cause de cette ressortingction – vous avez presque toujours besoin d’un InputStreamReader autour d’un FileInputStream ou de l’équivalent pour la sortie 🙁

Infirmière, infirmière – où sont mes médicaments?

EDIT: Il me semble que cela n’a pas vraiment répondu à la question. La vraie réponse est sans doute que «personne n’y a pensé» ou «une personne impliquée pensait que c’était une mauvaise idée». Je suggère fortement que les classes d’utilitaires internes fournissant les noms ou les jeux de caractères évitent la duplication autour du code … Ou vous pourriez simplement utiliser celle que nous avons utilisée chez Google lorsque cette réponse a été écrite pour la première fois . (Notez qu’à partir de Java 7, vous utiliseriez simplement StandardCharsets place.)

En Java 1.7

import java.nio.charset.StandardCharsets

ex: StandardCharsets.UTF_8 StandardCharsets.US_ASCII

L’état actuel de l’API de codage laisse à désirer. Certaines parties de l’API Java 6 n’acceptent pas le jeu de Charset à la place d’une chaîne (dans logging , dom.ls , PrintStream , il peut y en avoir d’autres). Cela n’aide pas que les encodages soient supposés avoir des noms canoniques différents pour les 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 shinyes sur la façon de les réparer.


En aparté…

Vous pouvez rechercher les noms de l’implémentation Java 6 de Sun ici .

Pour UTF-8, les valeurs canoniques sont "UTF-8" pour java.nio et "UTF8" pour java.lang et java.io Les seuls encodages dont la spécification nécessite un JRE sont: US-ASCII; ISO-8859-1; UTF-8; UTF-16BE; UTF-16LE; UTF-16 .

Il y a longtemps, j’ai défini une classe d’utilitaire avec les constantes UTF_8, ISO_8859_1 et US_ASCII Charset.

Il y a quelque temps (2 ans et plus), j’ai effectué un test de performance simple entre new Ssortingng( byte[], Charset ) et new Ssortingng( byte[], Ssortingng charset_name ) et découvert que cette dernière implémentation est CONSIDERABLEMENT plus rapide. Si vous regardez le code source sous le capot, vous verrez qu’il s’agit bien d’un cheminement différent.

Pour cette raison, j’ai inclus un utilitaire dans la même classe

 public static Ssortingng ssortingngFromByteArray ( final byte[] array, final Charset charset ) { try { return new Ssortingng( array, charset.name( ) ) } catch ( UnsupportedEncodingException ex ) { // cannot happen } } 

Pourquoi le constructeur Ssortingng (byte [], Charset) ne fait pas la même chose, me bat.