Comment définir correctement le codage de caractères par défaut utilisé par la machine virtuelle Java (1.5.x) par programme?
J'ai lu que -Dfile.encoding=whatever
était le chemin à suivre pour les anciennes JVM ... Je n'ai pas ce luxe pour des raisons qui m'empêcheraient d'entrer.
J'ai essayé:
System.setProperty("file.encoding", "UTF-8");
Et la propriété est définie, mais elle ne semble pas obliger le dernier appel getBytes à utiliser UTF8:
System.setProperty("file.encoding", "UTF-8");
byte inbytes[] = new byte[1024];
FileInputStream fis = new FileInputStream("response.txt");
fis.read(inbytes);
FileOutputStream fos = new FileOutputStream("response-2.txt");
String in = new String(inbytes, "UTF8");
fos.write(in.getBytes());
Malheureusement, la propriété file.encoding
doit être spécifiée au démarrage de la machine virtuelle Java. au moment où vous entrez votre méthode principale, le codage de caractères utilisé par String.getBytes()
et les constructeurs par défaut de InputStreamReader
et OutputStreamWriter
ont été mis en cache de manière permanente.
Comme Edward Grech souligne, dans un cas spécial comme celui-ci, la variable d'environnement Java_TOOL_OPTIONS
peut être utilisée pour spécifiez cette propriété, mais cela se fait normalement comme ceci:
Java -Dfile.encoding=UTF-8 … com.x.Main
Charset.defaultCharset()
reflétera les modifications apportées à la propriété file.encoding
, mais la plupart du code des bibliothèques principales Java devant déterminer le codage de caractères par défaut n'utilise pas ce mécanisme.
Lors du codage ou du décodage, vous pouvez interroger la propriété file.encoding
ou Charset.defaultCharset()
pour rechercher le codage par défaut actuel et utiliser la méthode ou la surcharge de constructeur appropriée pour le spécifier.
À partir de la interface JVM ™ Tool documentation…
Etant donné que la ligne de commande ne peut pas toujours être consultée ou modifiée, par exemple dans les ordinateurs virtuels intégrés ou simplement dans les ordinateurs virtuels lancés profondément dans des scripts, une variable
Java_TOOL_OPTIONS
est fournie afin que les agents puissent être lancés dans ces cas.
En définissant la variable d'environnement (Windows) Java_TOOL_OPTIONS
sur -Dfile.encoding=UTF8
, la propriété (Java) System
est définie automatiquement à chaque démarrage d'une machine virtuelle. Vous saurez que le paramètre a été récupéré car le message suivant sera envoyé à System.err
:
Picked up Java_TOOL_OPTIONS: -Dfile.encoding=UTF8
J'ai un moyen hacky qui fonctionne vraiment!
System.setProperty("file.encoding","UTF-8");
Field charset = Charset.class.getDeclaredField("defaultCharset");
charset.setAccessible(true);
charset.set(null,null);
De cette façon, vous allez tromper JVM qui penserait que le jeu de caractères n'est pas défini et le redéfinit sur UTF-8, au moment de l'exécution!
Je pense qu'une meilleure approche que de définir le jeu de caractères par défaut de la plate-forme, d'autant plus que vous semblez avoir des restrictions pour affecter le déploiement de l'application, sans parler de la plate-forme, consiste à appeler le beaucoup plus sûr String.getBytes("charsetName")
. Ainsi, votre application ne dépend pas d'éléments indépendants de sa volonté.
Personnellement, j'estime que String.getBytes()
devrait être déconseillé, car cela a causé de graves problèmes dans un certain nombre de cas que j'ai vus, où le développeur n'a pas tenu compte du jeu de caractères par défaut éventuellement modifié.
Je ne peux pas répondre à votre question initiale, mais j'aimerais vous donner quelques conseils. Ne dépendez pas du codage par défaut de la machine virtuelle. Il est toujours préférable de spécifier explicitement le codage souhaité ("UTF-8") dans votre code. De cette façon, vous savez que cela fonctionnera même sur différents systèmes et configurations JVM.
Essaye ça :
new OutputStreamWriter( new FileOutputStream("Your_file_fullpath" ),Charset.forName("UTF8"))
Nous avions les mêmes problèmes. Nous avons méthodiquement essayé plusieurs suggestions de cet article (et d’autres) en vain. Nous avons également essayé d'ajouter le -Dfile.encoding=UTF8
et rien ne semblait fonctionner.
Pour les personnes confrontées à ce problème, l'article suivant nous a enfin aidé à comprendre comment le paramètre régional peut décomposer unicode/UTF-8
dans Java/Tomcat
http://www.jvmhost.com/articles/locale-breaks-unicode-utf-8-Java-Tomcat
Définir les paramètres régionaux correctement dans le fichier ~/.bashrc
a fonctionné pour nous.
Si vous utilisez Spring Boot et souhaitez passer l'argument file.encoding
dans la machine virtuelle Java, vous devez l'exécuter comme suit:
mvn spring-boot:run -Drun.jvmArguments="-Dfile.encoding=UTF-8"
cela était nécessaire pour nous puisque nous utilisions JTwig
modèles et que le système d’exploitation possédait ANSI_X3.4-1968
que nous avions découvert par System.out.println(System.getProperty("file.encoding"));
J'espère que ça aide quelqu'un!
J'ai essayé beaucoup de choses, mais l'exemple de code ici fonctionne parfaitement. Lien
Le noeud du code est:
String s = "एक गाव में एक किसान";
String out = new String(s.getBytes("UTF-8"), "ISO-8859-1");
mvn clean install -Dfile.encoding=UTF-8 -Dmaven.repo.local=/path-to-m2
cette commande fonctionnait avec exec-maven-plugin pour résoudre l’erreur suivante lors de la configuration d’une tâche jenkins.
Java HotSpot(TM) 64-Bit Server VM warning: ignoring option MaxPermSize=512m; support was removed in 8.0
Error occurred during initialization of VM
Java.nio.charset.IllegalCharsetNameException: "UTF-8"
at Java.nio.charset.Charset.checkName(Charset.Java:315)
at Java.nio.charset.Charset.lookup2(Charset.Java:484)
at Java.nio.charset.Charset.lookup(Charset.Java:464)
at Java.nio.charset.Charset.defaultCharset(Charset.Java:609)
at Sun.nio.cs.StreamEncoder.forOutputStreamWriter(StreamEncoder.Java:56)
at Java.io.OutputStreamWriter.<init>(OutputStreamWriter.Java:111)
at Java.io.PrintStream.<init>(PrintStream.Java:104)
at Java.io.PrintStream.<init>(PrintStream.Java:151)
at Java.lang.System.newPrintStream(System.Java:1148)
at Java.lang.System.initializeSystemClass(System.Java:1192)
Pas clair sur ce que vous faites et n'avez pas de contrôle sur ce point. Si vous pouvez interposer une classe OutputStream différente dans le fichier de destination, vous pouvez utiliser un sous-type de OutputStream qui convertit les chaînes en octets sous un jeu de caractères que vous définissez, par exemple UTF-8. Si UTF-8 modifié suffit à vos besoins, vous pouvez utiliser DataOutputStream.writeUTF(String)
:
byte inbytes[] = new byte[1024];
FileInputStream fis = new FileInputStream("response.txt");
fis.read(inbytes);
String in = new String(inbytes, "UTF8");
DataOutputStream out = new DataOutputStream(new FileOutputStream("response-2.txt"));
out.writeUTF(in); // no getBytes() here
Si cette approche n'est pas réalisable, il peut être utile de clarifier ici exactement ce que vous pouvez et ne pouvez pas contrôler en termes de flux de données et d'environnement d'exécution (bien que je sache que c'est parfois plus facile à dire qu'à déterminer). Bonne chance.
Après les commentaires de @Caspar sur la réponse acceptée, le moyen préféré de résoudre ce problème selon Sun est:
"modifier les paramètres régionaux de la plate-forme sous-jacente avant de démarrer votre programme Java."
http://bugs.Java.com/view_bug.do?bug_id=4163515
Pour docker, voir:
Mon équipe a rencontré le même problème sur des machines Windows .. puis est parvenue à le résoudre de deux manières:
a) Définir la variable d'environnement (même dans les préférences système Windows)
Java_TOOL_OPTIONS
- Dfile.encoding = UTF8
b) Introduisez l'extrait suivant dans votre pom.xml:
-Dfile.encoding=UTF-8
DANS
<jvmArguments>
-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=8001
-Dfile.encoding=UTF-8
</jvmArguments>
Récemment, je suis tombé sur le système Notes 6.5 d'une entreprise locale et j'ai découvert que le webmail afficherait des caractères non identifiables sur une installation Windows autre que celle de Zhongwen. J'ai creusé pendant plusieurs semaines en ligne, a découvert il y a quelques minutes à peine:
Dans les propriétés Java, ajoutez la chaîne suivante à Paramètres d'exécution.
-Dfile.encoding=MS950 -Duser.language=zh -Duser.country=TW -Dsun.jnu.encoding=MS950
Le réglage UTF-8 ne fonctionnerait pas dans ce cas.
J'utilise Amazon (AWS) Elastic Beanstalk et j'ai réussi à le remplacer par UTF-8.
Dans Elastic Beanstalk, accédez à Configuration> Logiciel, "Propriétés de l'environnement". Ajoutez (nom) Java_TOOL_OPTIONS avec (valeur) -Dfile.encoding = UTF8
Après la sauvegarde, l’environnement redémarre avec le codage UTF-8.
Nous définissons deux propriétés système ensemble, ce qui rend le système tout en utf8
file.encoding=UTF8
client.encoding.override=UTF-8