Pourquoi les noms de charset ne sont pas des constantes?
Les problèmes de jeu de caractères sont confus et compliqués par eux-mêmes, mais en plus de cela, vous devez vous souvenir des noms exacts de vos jeux de caractères. Est-ce "utf8"
? Ou "utf-8"
? Ou peut-ê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
?
6 réponses
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 doivent être présents, donc des constantes auraient pu être faites pour celles-ci il y a longtemps. Je ne sais pas pourquoi ils ne l'étaient pas.
JDK 1.4 a fait une bonne chose en introduisant le type Charset. À ce stade, ils n'auraient plus voulu fournir de constantes de chaîne, puisque le but est de faire en sorte que tout le monde utilise des instances Charset. Alors pourquoi ne pas fournir le six constantes de jeu de caractères standard, alors? J'ai demandé à Martin Buchholz puisqu'il se trouve être assis juste à côté de moi, et il a dit qu'il n'y avait pas de raison vraiment particulièrement bonne, sauf qu'à l'époque, les choses étaient encore à moitié cuites-trop peu D'API JDK avaient été modernisées pour accepter Charset, et de celles qui étaient, les surcharges Charset
C'est triste que ce n'est que dans JDK 1.6 qu'ils ont finalement fini de tout équiper avec des surcharges de Charset. Et que cette situation de performance en arrière existe toujours (la raison pour laquelle est incroyablement bizarre 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 est lié (bien que cette bibliothèque ne soit pas encore vraiment publiée).
Mise à Jour: un StandardCharsets
la classe est dans le JDK 7.
Deux ans plus tard, et les StandardCharsets de Java 7 définissent 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.
Je dirais que nous pouvons faire beaucoup mieux que cela... pourquoi les jeux de caractères garantis-à-être-disponibles ne sont-ils pas accessibles directement? Charset.UTF8
devrait être une référence au Charset
, pas le nom en tant que chaîne. De cette façon, nous n'aurions pas à gérer UnsupportedEncodingException
partout.
Rappelez - vous, je pense aussi que.NET a choisi une meilleure stratégie en utilisant par défaut UTF-8 partout. Il a ensuite foiré en nommant la propriété d'encodage" operating system default " simplement Encoding.Default
- qui n'est pas la valeur par défaut sein de .NET lui-même :(
Retour à propos du support du jeu de caractères de Java-pourquoi n'y a-t-il pas de constructeur pour FileWriter
/FileReader
qui prend un Charset
? Fondamentalement, ce sont des classes presque inutiles en raison de cette restriction - vous avez presque toujours besoin d'un InputStreamReader
autour d'un FileInputStream
ou l'équivalent pour la sortie : (
Infirmière, Infirmière - où est mon médicament?
EDIT: il me semble que cela n'a pas vraiment répondu à la question. La vraie réponse est probablement soit "personne impliqué n'y a pensé" ou "quelqu'un qui pensait que c'était une mauvaise idée."Je suggère fortement que les classes d'utilité 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 qu'à partir de Java 7, vous utiliseriez simplementStandardCharsets
au lieu de cela.)
En Java 1.7
import java.nio.charset.StandardCharsets
Ex:
StandardCharsets.UTF_8
StandardCharsets.US_ASCII
L'état actuel de l'API d'encodage laisse à désirer. Certaines parties de L'API Java 6 n'acceptent pas Charset
à la place d'une chaîne (in 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 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 réparer.
Comme un hormis...
Vous pouvez rechercher les noms de L'implémentation Java 6 de Sun ici .
Pour de l'UTF-8, les canonique valeurs sont "UTF-8"
pour java.nio
et "UTF8"
pour java.lang
et java.io
. Les seuls encodages que la spécification nécessite un JRE à prendre en charge sont: US-ASCII; ISO-8859-1; UTF-8; UTF-16BE; UTF-16LE; UTF-16.
J'ai depuis longtemps défini une classe utilitaire avec les constantes Utf_8, ISO_8859_1 et US_ASCII Charset.
Aussi, il y a longtemps ( 2+ ans ) j'ai fait un test de performance simple entre new String( byte[], Charset )
et new String( byte[], String charset_name )
et j'ai découvert que cette dernière implémentation est considérablement plus rapide. Si vous jetez un oeil 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
public static String stringFromByteArray (
final byte[] array,
final Charset charset
)
{
try
{
return new String( array, charset.name( ) )
}
catch ( UnsupportedEncodingException ex )
{
// cannot happen
}
}
Pourquoi le String (byte[], charset ) constructeur ne fait pas la même chose, me bat.