sen*_*erj 5 java netbeans arguments
我正在编写一个 Netbeans java 程序来处理参数中的中文字符。我能够在编码中使用 unicode 代码和汉字,并且它们可以正确编译并显示在控制台上。但是,当我通过项目属性运行参数传递汉字时,它们都变成了??????。我已经将项目编码设置为UTF-8VM 选项-Dfile.encoding=UTF-8。这是我的编码,请帮忙。
public static void main(String[] args) {\n String test = "\\u5973\\u58eb";\n System.out.println(test); //works\n String test2 = "\xe5\xa5\xb3\xe5\xa3\xab2";\n System.out.println(test2); //works\n System.out.println(args[0]); //copy&paste test2 to argument, not works, showing ??\n}\nRun Code Online (Sandbox Code Playgroud)\n注意:我使用 jdk 1.8.0_202、Ant v1.10.4、Windows 10、Netbeans 10,用于 Netbeans 输出和 termianl 的字体是等宽14,项目是使用 Netbeans“java 应用程序”创建的。在 Netbeans 中或 Windows 命令提示符 chcp 65001 上运行时会出现问题-Dfile.encoding=UTF-8.
注意:根据 skomisa 的建议,我进一步测试了 Windows“使用 unicode utf8 进行全球语言支持”检查。我也不再使用 Netbeans,而是使用该 jar 通过 chcp 65001 在 Windows cmd 上运行。
\nD:\\.......>java -cp dist/myjar.jar -Dfile.encoding=UTF8 java.mypackage.TestUTF8 \xe5\xa5\xb3\xe5\xa3\xab\n\xe5\xa5\xb3\xe5\xa3\xab\n\xe5\xa5\xb3\xe5\xa3\xab2\n\xc3\xa5\xc2\xa5\xc2\xb3\xc3\xa5\xc2\xa3\xc2\xab\n\nD:\\.......>java -cp dist/myjar.jar java.mypackage.TestUTF8 \xe5\xa5\xb3\xe5\xa3\xab\n??\n??2\n\xe5\xa5\xb3\xe5\xa3\xab\nRun Code Online (Sandbox Code Playgroud)\n因此,对于-Dfile.encoding=UTF8(第一次运行),编码中的常量字符串有效,而参数则无效。没有-Dfile.encoding(第二次运行),代码内常量将无法工作,而参数可以工作。但我两者都需要。我的程序和程序参数中有中文常量字符串。有人可以告诉我可以做什么吗?
基于对 SO 上类似问题的回答,似乎将 Unicode 参数传递给 Java 应用程序从未正常工作。没有简单的解决方案,但您可以使用JNA (Java Native Access) 解决此问题。
\nJNA 允许您从 Java 调用 Windows API 方法,而无需使用native代码。因此,在 Java 应用程序中,您可以直接调用 Win API 方法,例如GetCommandLineW()和CommandLineToArgvW(),以访问有关用于调用程序的命令行的详细信息,包括传递的任何参数。这两种方法都支持 Unicode。
执行此操作的代码并不简单,但也不是过于复杂。下面的方法基于 Sergey Karpushin在Passing command line unicode argument to Java code 的回答中的代码
\n为了编译代码,您将需要几个 jar:jna.jar和jna-platform.jar。您可以从JNA 5.10.0 下载的dist目录或从 Maven获取这些内容。
\n此方法既可以在 NetBeans 中使用,也可以在 Windows 10 的命令行中使用,但存在一些显着的差异:
\nCommandLineToArgvW()您可能会发现 NetBeans 中返回的参数与命令行中返回的参数之间存在差异。但这并不是真正的问题,因为您感兴趣的唯一参数是末尾的参数,这些参数位于包含 jar 文件名的参数之后。这是代码:
\npackage chinesearg;\n\nimport com.sun.jna.Native;\nimport com.sun.jna.Pointer;\nimport com.sun.jna.WString;\nimport com.sun.jna.ptr.IntByReference;\nimport com.sun.jna.win32.StdCallLibrary;\nimport java.util.ArrayList;\nimport java.util.List;\n\n// Proof of concept application which uses JNA to correctly process command\n// line arguments containing Chinese characters using JNA. \n//\n// Credit to Sergey Karpushin for the approach used in this this code.\n// See this SO answer: /sf/answers/2934643631/\npublic class ChineseArg {\n\n private final Kernel32 kernel32 = Native.load("kernel32", Kernel32.class);\n private final Shell32 shell32 = Native.load("shell32", Shell32.class);\n\n public static void main(String[] args) {\n\n String test = "\\u5973\\u58eb";\n System.out.println(test); //works\n String test2 = "\xe5\xa5\xb3\xe5\xa3\xab2";\n System.out.println(test2); //works\n System.out.println("args.length=" + args.length);\n for (int i=0; i< args.length; i++) {\n System.out.println("args[" + i + "] = "+args[i]);\n }\n String[] params = new ChineseArg().getCommandLineArguments();\n if (params == null) {\n System.out.println("getCommandLineArguments() returned null.");\n } else {\n int count = params.length;\n System.out.println("Number of params=" + count);\n for (int i = 0; i < count; i++) {\n System.out.println("params[" + i + "]=" + params[i]);\n }\n }\n }\n\n private String[] getCommandLineArguments() {\n\n System.out.println("Active code page is " + Kernel32.INSTANCE.GetConsoleCP());\n String[] ret = getFullCommandLine();\n List<String> argsOnly = null;\n\n for (int i = 0; i < ret.length; i++) {\n if (argsOnly != null) {\n argsOnly.add(ret[i]);\n } else if (ret[i].toLowerCase().endsWith(".jar")) {\n argsOnly = new ArrayList<>();\n }\n }\n if (argsOnly != null) {\n ret = argsOnly.toArray(new String[0]);\n }\n return ret;\n }\n\n private String[] getFullCommandLine() {\n\n IntByReference argc = new IntByReference();\n Pointer argv_ptr = shell32.CommandLineToArgvW(kernel32.GetCommandLineW(), argc);\n String[] argv = argv_ptr.getWideStringArray(0, argc.getValue());\n kernel32.LocalFree(argv_ptr);\n return argv;\n }\n}\n\ninterface Kernel32 extends StdCallLibrary {\n static Kernel32 INSTANCE = Native.load("kernel32", Kernel32.class, com.sun.jna.win32.W32APIOptions.DEFAULT_OPTIONS);\n WString GetCommandLineW();\n int GetConsoleCP();\n Pointer LocalFree(Pointer pointer);\n}\n\ninterface Shell32 extends StdCallLibrary {\n Pointer CommandLineToArgvW(WString command_line, IntByReference argc);\n}\nRun Code Online (Sandbox Code Playgroud)\n这是从命令提示符运行时的示例输出,显示第一个参数 ("\xe5\xa5\xb3\xe5\xa3\xab2") 被正确捕获:
\nC:\\Users\\johndoe>chcp 65001\nActive code page: 65001\n\nC:\\Users\\johndoe>java -Dfile.encoding=UTF-8 -jar "D:\\NB126\\ChineseArg\\dist\\ChineseArg.jar" "\xe5\xa5\xb3\xe5\xa3\xab2" "\\u5973\\u58eb"\n\xe5\xa5\xb3\xe5\xa3\xab\n\xe5\xa5\xb3\xe5\xa3\xab2\nargs.length=2\nargs[0] = ??2\nargs[1] = \\u5973\\u58eb\nActive code page is 65001\nNumber of params=2\nparams[0]=\xe5\xa5\xb3\xe5\xa3\xab2\nparams[1]=\\u5973\\u58eb\n\nC:\\Users\\johndoe>\nRun Code Online (Sandbox Code Playgroud)\n笔记:
\n