Passage d’un argument unicode en ligne de commande au code Java

Je dois passer l’argument de ligne de commande qui est japonais à la méthode principale Java. Si je tape des caractères Unicode dans la fenêtre de ligne de commande, il affiche “?????” ce qui est OK, mais la valeur transmise au programme Java est également ‘?????’. Comment puis-je obtenir la valeur correcte de l’argument passé par la fenêtre de commande? Voici un exemple de programme qui écrit dans un fichier la valeur fournie par l’argument de ligne de commande.

public static void main(Ssortingng[] args) { Ssortingng input = args[0]; try { Ssortingng filePath = "C:/Temp/abc.txt"; File file = new File(filePath); OutputStream out = new FileOutputStream(file); byte buf[] = new byte[1024]; int len; InputStream is = new ByteArrayInputStream(input.getBytes()); while ((len = is.read(buf)) > 0) { out.write(buf, 0, len); } out.close(); is.close(); } catch (Exception e) { e.printStackTrace(); } } 

Malheureusement, vous ne pouvez pas utiliser de manière fiable les caractères non-ASCII avec des applications en ligne de commande utilisant la bibliothèque stdlib du runtime Windows C, comme Java (et tous les langages de script non spécifiques à Windows, en réalité).

En effet, ils lisent leurs entrées et sorties à l’aide d’une page de code spécifique aux parameters régionaux, qui n’est jamais un fichier UTF, contrairement à tous les autres systèmes d’exploitation modernes qui utilisent UTF-8.

Bien que vous puissiez modifier la page de code d’un terminal en utilisant quelque chose d’autre à l’aide de la commande chcp , la prise en charge du codage UTF-8 sous chcp 65001 est interrompue de plusieurs manières qui risquent de chcp le chcp applications.

Si vous avez uniquement besoin du japonais, vous pouvez passer à la page de codes 932 (similaire à Shift-JIS) en définissant vos parameters régionaux (langue pour les applications non Unicode) dans les parameters régionaux) sur Japon. Cela échouera quand même pour les caractères qui ne sont pas dans cette page de code.

Si vous devez obtenir des caractères non-ASCII par le biais de la ligne de commande de manière fiable sous Windows, vous devez appeler directement la fonction GetCommandLineW API Win32 pour éviter la couche de code page à code système. Vous voudrez probablement faire cela en utilisant la JNA.

Malheureusement, le programme de lancement Java standard présente un bogue connu et persistant dans la gestion des arguments de ligne de commande Unicode sous Windows. Peut-être aussi sur d’autres plateformes. Pour Java 7 update 1, il était toujours en place.

Si vous vous sentez bien en programmation en C / C ++, essayez d’écrire votre propre programme de lancement. Certains lanceurs spécialisés pourraient ne pas être un gros problème … Il suffit de voir le premier exemple sur la page API JNI Invocation .

Une autre possibilité consiste à utiliser une combinaison d’encapsuleur Java et d’un fichier temporaire pour transmettre les parameters Unicode à une application Java. Voir mon blog Java, Xalan, les arguments de ligne de commande Unicode … pour plus de commentaires et le code wrapper.

Le problème est dû aux parameters régionaux de votre système. Changez votre locale en japonais et cela fonctionnerait.

Voici comment faire http://www.java.com/fr/download/help/locale.xml

Vous pouvez utiliser la JNA pour l’obtenir, voici un copier-coller de mon code:

 import java.util.ArrayList; import java.util.Arrays; import java.util.List; import org.apache.log4j.Logger; import com.sun.jna.Native; import com.sun.jna.Pointer; import com.sun.jna.WSsortingng; import com.sun.jna.ptr.IntByReference; import com.sun.jna.win32.StdCallLibrary; public class OsNativeWindowsImpl implements OsNative { private static Logger log = Logger.getLogger(OsNativeWindowsImpl.class); private Kernel32 kernel32; private Shell32 shell32; /** * This method will try to solve issue when java executable cannot transfer * argument in utf encoding. cyrillic languages screws up and application * receives ??????? instead of real text */ @Override public Ssortingng[] getCommandLineArguments(Ssortingng[] fallBackTo) { try { log.debug("In case we fail fallback would happen to: " + Arrays.toSsortingng(fallBackTo)); Ssortingng[] ret = getFullCommandLine(); log.debug("According to Windows API programm was started with arguments: " + Arrays.toSsortingng(ret)); List argsOnly = null; for (int i = 0; i < ret.length; i++) { if (argsOnly != null) { argsOnly.add(ret[i]); } else if (ret[i].toLowerCase().endsWith(".jar")) { argsOnly = new ArrayList<>(); } } if (argsOnly != null) { ret = argsOnly.toArray(new Ssortingng[0]); } log.debug("These arguments will be used: " + Arrays.toSsortingng(ret)); return ret; } catch (Throwable t) { log.error("Failed to use JNA to get current program command line arguments", t); return fallBackTo; } } private Ssortingng[] getFullCommandLine() { try { // int pid = kernel32.GetCurrentProcessId(); IntByReference argc = new IntByReference(); Pointer argv_ptr = getShell32().CommandLineToArgvW(getKernel32().GetCommandLineW(), argc); Ssortingng[] argv = argv_ptr.getWideSsortingngArray(0, argc.getValue()); getKernel32().LocalFree(argv_ptr); return argv; } catch (Throwable t) { throw new RuntimeException("Failed to get program arguments using JNA", t); } } private Kernel32 getKernel32() { if (kernel32 == null) { kernel32 = (Kernel32) Native.loadLibrary("kernel32", Kernel32.class); } return kernel32; } private Shell32 getShell32() { if (shell32 == null) { shell32 = (Shell32) Native.loadLibrary("shell32", Shell32.class); } return shell32; } } interface Kernel32 extends StdCallLibrary { int GetCurrentProcessId(); WSsortingng GetCommandLineW(); Pointer LocalFree(Pointer pointer); } interface Shell32 extends StdCallLibrary { Pointer CommandLineToArgvW(WSsortingng command_line, IntByReference argc); } 

En plus de log4j bien connu, ce code dépend également de

  net.java.dev.jna jna 4.3.0  

Java fonctionne en interne avec Unicode. Par conséquent, lors de la compilation de fichiers de code source utilisant un codage chinois tel que Big5 ou GB2312, vous devez spécifier le codage au compilateur afin de le convertir correctement en Unicode.

 javac -encoding big5 sourcefile.java 

ou

 javac -encoding gb2312 sourcefile.java 

Référence: http://www.chinesecomputing.com/programming/java.html