La réponse évidente est d'utiliser Charset.defaultCharset()
mais nous avons récemment découvert que ce n'était peut-être pas la bonne réponse. On m'a dit que le résultat était différent du jeu de caractères par défaut réel utilisé par les classes java.io à plusieurs occasions. Il semble que Java conserve deux jeux de caractères par défaut. Quelqu'un a-t-il une idée de ce problème ?
Nous avons pu reproduire un cas d'échec. Il s'agit d'une erreur de l'utilisateur, mais il se peut qu'elle expose la cause profonde de tous les autres problèmes. Voici le code,
public class CharSetTest {
public static void main(String[] args) {
System.out.println("Default Charset=" + Charset.defaultCharset());
System.setProperty("file.encoding", "Latin-1");
System.out.println("file.encoding=" + System.getProperty("file.encoding"));
System.out.println("Default Charset=" + Charset.defaultCharset());
System.out.println("Default Charset in Use=" + getDefaultCharSet());
}
private static String getDefaultCharSet() {
OutputStreamWriter writer = new OutputStreamWriter(new ByteArrayOutputStream());
String enc = writer.getEncoding();
return enc;
}
}
Notre serveur requiert un jeu de caractères par défaut en Latin-1 pour gérer un encodage mixte (ANSI/Latin-1/UTF-8) dans un ancien protocole. Tous nos serveurs fonctionnent donc avec ce paramètre de la JVM,
-Dfile.encoding=ISO-8859-1
Voici le résultat sur Java 5,
Default Charset=ISO-8859-1
file.encoding=Latin-1
Default Charset=UTF-8
Default Charset in Use=ISO8859_1
Quelqu'un essaie de changer l'encodage au moment de l'exécution en définissant le file.encoding dans le code. Nous savons tous que cela ne fonctionne pas. Cependant, cela semble perturber defaultCharset() mais n'affecte pas le jeu de caractères par défaut utilisé par OutputStreamWriter.
Est-ce un bug ou une fonctionnalité ?
EDIT : La réponse acceptée montre la cause profonde du problème. Fondamentalement, vous ne pouvez pas faire confiance à defaultCharset() en Java 5, qui n'est pas l'encodage par défaut utilisé par les classes I/O. Il semble que Java 6 corrige ce problème.
0 votes
C'est étrange, car le defaultCharset utilise une variable statique qui n'est définie qu'une seule fois (selon la documentation - au démarrage de la VM). Quel vendeur de VM utilisez-vous ?
0 votes
J'ai pu reproduire ce problème sur Java 5, à la fois sur Sun/Linux et Apple/OS X.
0 votes
Cela explique pourquoi defaultCharset() ne met pas en cache le résultat. Je dois encore trouver quel est le vrai jeu de caractères par défaut utilisé par les classes IO. Il doit y avoir un autre jeu de caractères par défaut mis en cache quelque part ailleurs.
0 votes
@ZZ Coder, je suis toujours en train de faire des recherches sur ce sujet. La seule chose que je sais est que la méthode Charset.defaulyCharset() n'est pas appelée par sun.nio.cs.StreamEncoder dans la JVM 1.5. Dans la JVM 1.6, la méthode Charset.defaulyCharset() est appelée et donne les résultats attendus. L'implémentation de StreamEncoder dans la JVM 1.5 met en cache le codage précédent, d'une manière ou d'une autre.
0 votes
Pour votre information, il existe une proposition officielle visant à "spécifier UTF-8 comme jeu de caractères par défaut pour les API de Java SE, afin que les API qui dépendent du jeu de caractères par défaut se comportent de manière cohérente dans toutes les implémentations du JDK et indépendamment du système d'exploitation, de la locale et de la configuration de l'utilisateur". Voir JEP 400 : UTF-8 par défaut , mis à jour le 2021-03-30.