2011-10-05 39 views
11

我必须将日语命令行参数传递给Java主方法。如果我在命令行窗口中键入Unicode字符,它会显示'?????'这是可以的,但传递给java程序的值也是'?????'。如何获得通过命令窗口传递的参数的正确值?下面是示例程序,它将通过命令行参数提供的值写入文件。将命令行unicode参数传递给Java代码

public static void main(String[] args) { 
     String input = args[0]; 
     try { 
      String 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(); 
     } 
    } 
+1

它是否在改变,当你更改控制台窗口的字符集?哪个操作系统? – Andreas

+1

更改控制台窗口的charset无助于您。我正在使用Windows 2000 –

回答

0

问题出在您的系统区域设置。将您的语言环境更改为日语,它会起作用。

这里是如何做到这一点http://www.java.com/en/download/help/locale.xml

+0

我们不应该能够在不改变系统区域设置的情况下传递任何Unicode值(无论是日语还是韩语)?现在没有资源去做,会给它一个镜头。 –

+0

这只是单一语言的解决方法。如果在他/她的电脑上有超过1种非英语语言,该怎么办?如果其他应用程序(如记事本)可以处理非英文字母,则Java应用程序也必须能够在不更改系统区域设置的情况下执行此操作。请参阅下面http://stackoverflow.com/a/41923480/285060答案是不需要改变操作系统语言环境 –

-2

的Java内部工作使用Unicode,所以在编译使用的中国编码,如中文或GB2312的源代码文件时,你需要以指定编码编译器正确将其转换为Unicode。

javac -encoding big5 sourcefile.java 

javac -encoding gb2312 sourcefile.java 

参考:http://www.chinesecomputing.com/programming/java.html

+0

这是完全不相干的问题。问题是关于在args中用unicode符号调用应用程序。这不是关于编译其中包含unicode符号的源代码。 –

10

可惜你不能可靠地使用与使用Windows的C运行时的STDLIB,像Java(和相当多的命令行应用程序的非ASCII字符所有非Windows特定的脚本语言)。

这是因为默认情况下使用特定的语言环境的代码页,这是从来没有一个UTF,不像使用UTF-8所有其他现代操作系统读取输入和输出。

虽然您可以使用chcp命令将终端的代码页更改为其他内容,但在chcp 65001下对UTF-8编码的支持可能会以几种方式破坏,这些方式可能会使应用程序严重故障。

如果你只需要你的日本可以切换到代码页932(类似于为Shift-JIS)受您所在区域(区域设置“语言非Unicode应用程序”)设置为日本。对于不在该代码页中的字符,这仍然会失败。

如果您需要在Windows上可靠地通过命令行获取非ASCII字符,则需要直接调用Win32 API函数GetCommandLineW以避免编码至系统代码页层。可能你想用JNA来做到这一点。

5

不幸的是,标准Java启动程序在处理Windows上的Unicode命令行参数时存在一个已知和长期存在的错误。也许在其他一些平台上。对于Java 7更新1,它仍然存在。

如果您对C/C++编程感觉良好,您可以尝试编写自己的启动器。一些专门的启动器可能不是什么大问题......只要看到JNI Invocation API页面的最初示例。

另一种可能性是使用Java包装和临时文件的组合传递的Unicode参数的Java应用程序。查看我的博客Java, Xalan, Unicode command line arguments...了解更多评论和封装代码。

0

您可以使用JNA得到的是,这里的复制粘贴从我的代码:

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.WString; 
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 String[] getCommandLineArguments(String[] fallBackTo) { 
     try { 
      log.debug("In case we fail fallback would happen to: " + Arrays.toString(fallBackTo)); 
      String[] ret = getFullCommandLine(); 
      log.debug("According to Windows API programm was started with arguments: " + Arrays.toString(ret)); 

      List<String> 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 String[0]); 
      } 

      log.debug("These arguments will be used: " + Arrays.toString(ret)); 
      return ret; 
     } catch (Throwable t) { 
      log.error("Failed to use JNA to get current program command line arguments", t); 
      return fallBackTo; 
     } 
    } 

    private String[] getFullCommandLine() { 
     try { 
      // int pid = kernel32.GetCurrentProcessId(); 
      IntByReference argc = new IntByReference(); 
      Pointer argv_ptr = getShell32().CommandLineToArgvW(getKernel32().GetCommandLineW(), argc); 
      String[] argv = argv_ptr.getWideStringArray(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(); 

    WString GetCommandLineW(); 

    Pointer LocalFree(Pointer pointer); 
} 

interface Shell32 extends StdCallLibrary { 
    Pointer CommandLineToArgvW(WString command_line, IntByReference argc); 
} 

除了众所周知的log4j的这段代码也取决于

<dependency> 
    <groupId>net.java.dev.jna</groupId> 
    <artifactId>jna</artifactId> 
    <version>4.3.0</version> 
</dependency>