Java中控制台应用程序中的Unicode输入

sas*_*uke 5 java unicode console-application

我一直在尝试在我的Java应用程序中检索"unicode用户输入"以获取一个小实用程序代码段.问题是,它似乎正在Ubuntu"开箱即用",我猜想在UTF-8上运行OS宽编码,但从"cmd"运行时无法在Windows上运行.考虑的代码如下:

public class SerTest {

    public static void main(String[] args) throws Exception {
        testUnicode();
    }

    public static void testUnicode() throws Exception {
        System.out.println("Default charset: " +
           Charset.defaultCharset().name());
        BufferedReader in  =
           new BufferedReader(new InputStreamReader(System.in, "UTF-8"));
        System.out.printf("Enter '????? ???': ");
        String line = in.readLine();
        String s = "????? ???";
        byte[] sBytes = s.getBytes();
        System.out.println("strg bytes: " + Arrays.toString(sBytes));
        byte[] lineBytes = line.getBytes();
        System.out.println("line bytes: " + Arrays.toString(lineBytes));
        PrintStream out = new PrintStream(System.out, true, "UTF-8");
        out.print("--->" + s + "<----\n");
        out.print("--->" + line + "<----\n");
    }

}
Run Code Online (Sandbox Code Playgroud)

Ubuntu上的输出(不对配置进行任何更改):

me@host> javac SerTest.java  && java SerTest
Default charset: UTF-8
Enter '????? ???': ????? ???
strg bytes: [-48, -80, -48, -79, -48, -78, -48, -77, -48, -76, 32, -47, -115, -47, -114, -47, -113]
line bytes: [-48, -80, -48, -79, -48, -78, -48, -77, -48, -76, 32, -47, -115, -47, -114, -47, -113]
--->????? ???<----
--->????? ???<----
Run Code Online (Sandbox Code Playgroud)

Windows CMD提示输出(不受JAVA_TOOL_OPTIONS的影响):

E:\>chcp 65001
Active code page: 65001

E:\>java -Dfile.encoding=utf8 SerTest
Picked up JAVA_TOOL_OPTIONS: -Dfile.encoding=utf8
Default charset: UTF-8
Enter '????? ???': ??': ': ????? ???
strg bytes: [-48, -80, -48, -79, -48, -78, -48, -77, -48, -76, 32, -47, -115, -47, -114, -47, -113]
Exception in thread "main" java.lang.NullPointerException
        at SerTest.testUnicode(SerTest.java:26) # byte[] lineBytes = line.getBytes();
        at SerTest.main(SerTest.java:15)
Run Code Online (Sandbox Code Playgroud)

Eclipse控制台中的输出(使用JAVA_TOOL_OPTIONS后):

Default charset: UTF-8
Enter '????? ???': ????? ???
strg bytes: [-48, -80, -48, -79, -48, -78, -48, -77, -48, -76, 32, -47, -115, -47, -114, -47, -113]
Picked up JAVA_TOOL_OPTIONS: -Dfile.encoding=utf8
line bytes: [-48, -80, -48, -79, -48, -78, -48, -77, -48, -76, 32, -47, -115, -47, -114, -47, -113]
--->????? ???<----
--->????? ???<----
Run Code Online (Sandbox Code Playgroud)

在Eclipse控制台上,它正在工作,因为我添加了一个系统范围的环境变量(JAVA_TOOL_OPTIONS),如果可能的话我想避免.

Eclipse控制台中的输出(删除 JAVA_TOOL_OPTIONS后):

Default charset: UTF-8
Enter '????? ???': ????? ???
strg bytes: [-48, -80, -48, -79, -48, -78, -48, -77, -48, -76, 32, -47, -115, -47, -114, -47, -113]
line bytes: [-61, -112, -62, -80, -61, -112, -62, -79, -61, -112, -62, -78, -61, -112, -62, -77, -61, -112, -62, -76, 32, -61, -111, -17, -65, -67, -61, -111, -59, -67, -61, -111, -17, -65, -67]
--->????? ???<----
--->абвгд Ñ?ÑŽÑ?<----
Run Code Online (Sandbox Code Playgroud)

所以我的问题是:到底发生了什么?需要进行哪些代码更改才能确保此代码段适用于所有类型的"Unicode"输入?

很抱歉这个冗长的问题,并提前感谢,
佐助

McD*_*ell 4

一些注意事项:

  • -Dfile.encoding=utf8不受支持可能会导致意外的副作用:

J2SE 平台规范不要求“file.encoding”属性;它是 Sun 实现的内部细节,不应由用户代码检查或修改。它也是只读的;从技术上讲,不可能支持在命令行上或在程序执行期间的任何其他时间将此属性设置为任意值。

  • 该类Console将检测并使用终端编码,但在 Windows 上不支持 65001 (UTF-8) - 至少,我上次尝试时不支持

我相信在 cmd.exe 中使用 Unicode 的正确且有记录的方法是使用WriteConsoleWReadConsoleW

当我看到这个时,我写了几篇博客文章: