2009-08-26 8 views
6

J'ai une application Java qui reçoit des données sur un socket en utilisant un InputStreamReader. Il rend compte de « Cp1252 » de sa méthode getEncoding:Comment spécifier une valeur de file.encoding Java cohérente avec la page de code Windows sous-jacente?

/* java.net. */ Socket Sock = ...; 
InputStreamReader is = new InputStreamReader(Sock.getInputStream()); 
System.out.println("Character encoding = " + is.getEncoding()); 
// Prints "Character encoding = Cp1252" 

qui ne correspond pas nécessairement ce que les rapports du système comme la page de code. Par exemple:

 
C:\>chcp 
Active code page: 850 

L'application peut recevoir octet 0x81, qui code page 850 représente le caractère ü. Le programme interprète cet octet avec la page de code 1252, qui ne définit aucun caractère à cette valeur, donc j'obtiens un point d'interrogation à la place.

j'ai pu contourner ce problème pour un client qui a utilisé la page de code 850 en ajoutant une autre option de ligne de commande dans le fichier batch qui lance l'application:

 
java.exe -Dfile.encoding=Cp850 ... 

Mais pas tous mes clients utilisent le code page 850, bien sûr. Comment puis-je obtenir Java pour utiliser une page de code compatible avec le système Windows sous-jacent? Ma préférence serait quelque chose que je pouvais mettre dans le fichier de commandes, laissant le code Java intact:

 
ENC=... 
java.exe -Dfile.encoding=%ENC% ... 

Répondre

5

En ce qui concerne le snippit de code, la bonne réponse est d'utiliser le appropriate constructor pour InputStreamReader qui fait la conversion de code correct . De cette façon, peu importe le codage par défaut du système, vous savez que vous obtenez un encodage correct qui correspond à ce que vous obtenez sur le socket.

Ensuite, vous pouvez spécifier l'encodage lorsque vous écrivez des fichiers si nécessaire, plutôt que de compter sur l'encodage du système, mais bien sûr quand ils ouvrent des fichiers sur ce système, ils peuvent avoir des problèmes. 8, de sorte que vous pouvez écrire le fichier en UTF-8 si vous avez besoin de (en interne Java représente toutes les chaînes comme 16 bits unicode).

Je pense que c'est la «bonne» solution en général qui serait la plus compatible avec la plus grande gamme de systèmes sous-jacents.

+0

+1. BTW Sur mon système Windows 7, la page de codes active est 850, mais Java signale que "Cp1252" est la propriété système "file.encoding". –

+1

Les clients et le serveur doivent être configurés avec le même codage, quel qu'il soit pour un client donné. Une application non-Java envoie des données de caractères au serveur à l'aide de la page de codes locale, le serveur stocke les données et, plus tard, le serveur l'envoie à l'application Java. Personne ne stocke ce que la page de code est, parce que tant que tout le monde utilise le même, cela n'a pas d'importance. Le problème est que l'application Java ne coopère pas; il utilise toujours Cp1252. (La "bonne" solution consiste à changer le protocole pour forcer tout, par exemple, UTF-8, mais un changement de protocole casse toutes les installations existantes.) –

+0

Ensuite, il semble que G_A ait votre réponse. Une autre option consiste à faire en sorte que cette application non-Java signale à votre application Java ce qu'elle pense être l'encodage, puis utilisez le constructeur approprié, comme indiqué ci-dessus. – Yishai

4

Windows a la complication supplémentaire d'avoir deux pages de code actives. Dans votre exemple, 1252 et 850 sont corrects, mais ils dépendent de la façon dont le programme est exécuté. Pour les applications GUI, Windows utilisera la page de code ANSI, qui pour les langues d'Europe occidentale sera généralement 1252. Cependant, la ligne de commande indiquera la page de codes OEM qui est 850 pour les mêmes paramètres régionaux.

+0

Vous avez fait des déclarations vraies, mais je ne suis pas sûr de savoir comment ils répondent à ma question. Évidemment, la page de codes OEM est celle avec laquelle le programme Java doit être compatible. Alors, comment choisir une valeur 'file.encoding' basée sur cela? La façon dont le programme est exécuté est via 'java.exe'. –

4

Si la valeur de page de code qui revient d'une commande chcp renvoie la valeur que vous avez besoin, vous pouvez utiliser la commande suivante pour obtenir la page de code

C:\>for /F "Tokens=4" %I in ('chcp') Do Set CodePage=%I 

Ceci définit la variable CodePage au code valeur de la page retour de chcp

C:\>echo %CodePage% 
437 

Vous pouvez utiliser cette valeur dans votre fichier de chauve-souris par préfixant avec Cp

C:\>echo Cp%CodePage% 
Cp437 

Si, lorsque vous mettez cela dans un fichier de chauve-souris, le% I valeurs de la première commande devront être remplacés par %% Je

+0

Cela semblait prometteur, mais il repose sur certaines hypothèses concernant le format de la sortie 'chcp', qui peut différer sur les systèmes non anglais. En allemand, par exemple, la page de codes est dans le jeton 3, et il y a une période après le numéro: "Aktive Codepage: 850." –

+0

Voici comment cela fonctionne même pour un système allemand: 'FOR/F" TOKENS = 2 DELIMS = :."%% I IN ('chcp') DO SET cp = %% I', puis rogner les espaces avec' set cp =% cp: =% 'et finalement' echo Cp% cp% ' – fubar

+0

Voir cette solution ici: [Get page de code Windows cmd avec un fichier de commandes ou une commande unique] (http://stackoverflow.com/a/26675217/2773737) – fubar

6

L'encodage par défaut utilisé par cmd.exe est Cp850 (ou quoi que CP est natif « OEM » à l'OS); le codage du système est Cp1252 (ou quel que soit le CP "ANSI" natif du système d'exploitation). Gory details here. Une façon de découvrir le codage de la console serait de le faire via native code (voir GetConsoleOutputCP pour le codage de console actuel, voir GetACP pour le codage "ANSI" par défaut; etc.). La modification du codage via le commutateur -D va affecter tous vos mécanismes de codage par défaut, y compris redirigé stdout/stdin/stderr. Ce n'est pas une solution idéale.

Je suis venu avec ce script WSH qui peut définir la console à la page de code ANSI du système, mais n'a pas compris comment basculer par programme vers une police TrueType.

'file: setacp.vbs 
'usage: cscript /Nologo setacp.vbs 
Set objShell = CreateObject("WScript.Shell") 
'replace ACP (ANSI) with OEMCP for default console CP 
cp = objShell.RegRead("HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001" &_ 
           "\Control\Nls\CodePage\ACP") 
WScript.Echo "Switching console code page to " & cp 
objShell.Exec "chcp.com " & cp 

(Ceci est mon premier script WSH, il peut donc être erronée - Je ne suis pas familier avec les autorisations de lecture de registre.)

En utilisant une police TrueType est une autre exigence pour l'utilisation de la norme ANSI/Unicode avec cmd.exe . Je vais regarder un changement programmatique à une meilleure police lorsque le temps le permet.

Questions connexes