当前位置: 首页 > 知识库问答 >
问题:

java项目属性中的Netbeans汉字运行参数

云宜人
2023-03-14

我正在编写一个Netbeans java程序来处理参数中的汉字。我能够在我的编码中使用unicode代码和中文字符,它们能够正确编译并显示在控制台上。然而,当我通过project properties run参数传递汉字时,它们都会变成?????。我已经将我的项目编码设置为UTF-8和VM选项-Dfile。编码=UTF-8。这是我的代码,请帮忙。

public static void main(String[] args) {
    String test = "\u5973\u58eb";
    System.out.println(test);      //works
    String test2 = "女士2";
    System.out.println(test2);     //works
    System.out.println(args[0]);   //copy&paste test2 to argument, not works, showing ??
}

NB:我使用jdk 1.8。0_202,蚂蚁v1.10.4,视窗10,网络豆10,用于网络豆输出和termianl的字体是monospaced14,项目是使用网络豆“java应用程序”创建的。当使用-Dfile.encoding=UTF-8在Netbean或Windows命令提示符chcp 65001中运行时,会出现问题。

注意:根据skomisa的建议,我进一步测试了视窗“使用Unicode utf8进行全球语言支持”。我也远离Netbean,但使用jar在chcp 65001的Windows cmd上运行。

D:\.......>java -cp dist/myjar.jar -Dfile.encoding=UTF8 java.mypackage.TestUTF8 女士
女士
女士2
女士

D:\.......>java -cp dist/myjar.jar java.mypackage.TestUTF8 女士
??
??2
女士

所以使用-Dfile。encoding=UTF8(首次运行),编码中的常量字符串有效,而参数无效。没有-d文件。编码(第二次运行),在代码中常量不起作用,而参数起作用。但我两者都需要。我的程序和程序参数中都有中文常量字符串。谁能告诉我能做些什么吗。


共有1个答案

黄博艺
2023-03-14

基于对类似问题的回答,似乎将Unicode参数传递给Java应用程序从未正常工作过。没有简单的解决方案,但可以使用JNA(Java原生访问)解决这个问题。

JNA允许您从Java调用Windows API方法,而无需使用nativecode。因此,在Java应用程序中,可以直接调用Win API方法,例如GetCommandLineW()CommandLineToArgvW(),以访问用于调用程序的命令行的详细信息,包括传递的任何参数。这两种方法都支持Unicode。

实现这一点的代码并不琐碎,但也不太复杂。下面的方法基于Sergey Karpushin的代码,该代码回答了将命令行unicode参数传递给Java代码的问题

要编译代码,您需要几个JAR:jna。jar和jna平台。罐子您可以从JNA 5.10.0下载的dist目录或Maven获取这些信息。

这种方法既适用于NetBeans,也适用于Windows 10上的命令行,不过有一些显著的区别:

  • 必须从命令行调用chcp 65001,并指定-Dfile。在java中,encoding=UTF-8。exe呼叫
  • 在提取由CommandLineToArgvW()返回的参数时,您可能会看到NetBeans中返回的参数与从命令行返回的参数之间存在差异。但这并不是一个真正的问题,因为您感兴趣的唯一参数是末尾的参数,它们位于包含jar文件名的参数之后

这是代码:

package chinesearg;

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;
import java.util.ArrayList;
import java.util.List;

// Proof of concept application which uses JNA to correctly process command
// line arguments containing Chinese characters using JNA. 
//
// Credit to Sergey Karpushin for the approach used in this this code.
// See this SO answer: https://stackoverflow.com/a/41923480/2985643
public class ChineseArg {

    private final Kernel32 kernel32 = Native.load("kernel32", Kernel32.class);
    private final Shell32 shell32 = Native.load("shell32", Shell32.class);

    public static void main(String[] args) {

        String test = "\u5973\u58eb";
        System.out.println(test);      //works
        String test2 = "女士2";
        System.out.println(test2);     //works
        System.out.println("args.length=" + args.length);
        for (int i=0; i< args.length; i++) {
            System.out.println("args[" + i + "] = "+args[i]);
        }
        String[] params = new ChineseArg().getCommandLineArguments();
        if (params == null) {
            System.out.println("getCommandLineArguments() returned null.");
        } else {
            int count = params.length;
            System.out.println("Number of params=" + count);
            for (int i = 0; i < count; i++) {
                System.out.println("params[" + i + "]=" + params[i]);
            }
        }
    }

    private String[] getCommandLineArguments() {

        System.out.println("Active code page is " + Kernel32.INSTANCE.GetConsoleCP());
        String[] ret = getFullCommandLine();
        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]);
        }
        return ret;
    }

    private String[] getFullCommandLine() {

        IntByReference argc = new IntByReference();
        Pointer argv_ptr = shell32.CommandLineToArgvW(kernel32.GetCommandLineW(), argc);
        String[] argv = argv_ptr.getWideStringArray(0, argc.getValue());
        kernel32.LocalFree(argv_ptr);
        return argv;
    }
}

interface Kernel32 extends StdCallLibrary {
    static Kernel32 INSTANCE = Native.load("kernel32", Kernel32.class, com.sun.jna.win32.W32APIOptions.DEFAULT_OPTIONS);
    WString GetCommandLineW();
    int GetConsoleCP();
    Pointer LocalFree(Pointer pointer);
}

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

这是从命令提示符运行时的示例输出,显示第一个参数(“女士2”)被正确捕获:

C:\Users\johndoe>chcp 65001
Active code page: 65001

C:\Users\johndoe>java -Dfile.encoding=UTF-8 -jar "D:\NB126\ChineseArg\dist\ChineseArg.jar" "女士2"  "\u5973\u58eb"
女士
女士2
args.length=2
args[0] = ??2
args[1] = \u5973\u58eb
Active code page is 65001
Number of params=2
params[0]=女士2
params[1]=\u5973\u58eb

C:\Users\johndoe>

笔记:

  • 这段代码解决了Windows环境中的一个限制。我不知道如果这段代码在macOS或Linux上运行会发生什么。
  • 虽然这违背了您问题的精神,但还有一种替代方法:将参数作为转义Unicode传递给应用程序。使用Apache的StringEscape eUtils.unescapeJava()取消数据转义是很简单的。如果这是可行的,就根本不需要JNA。
 类似资料:
  • 我是vaadin的新手,当我试图创建一个新的项目时,出现了这个问题...我在谷歌上看了看,但找不到任何解决方案 总时间:4.665秒完成时间:Sat Jun 03 23:53:27 NPT 2017

  • 如何更改项目运行时平台? (standard NetBeans[8.1]Java Project[Java Application]) 详细信息: 在NetBeans 8.1中使用Ubuntu 我已经安装了JDK 1.6,JDK 1.7+JDK 1.8 我的项目平台是Java6. 我的系统默认Java是Java7。 NetBeans-IDE是用Java8启动的。 我想要的是: Project-Pl

  • 我是java语言的新手。我试着做我的第一个节目参考YouTube。但当我点击“运行”按钮时,它就不起作用了。我不知道为什么,但所有的构建或代码都是成功的。也许我有一些小错误…(?)有人能帮忙吗?在此输入图像说明

  • Project 对象提供了一些标准的属性,您可以在构建脚本中很方便的使用他们. 下面列出了常用的属性: Name Type Default Value project Project Project 实例对象 name String 项目目录的名称 path String 项目的绝对路径 description String 项目描述 projectDir File 包含构建脚本的目录 build

  • 问题内容: 我正在编写一个maven插件,该插件必须使用特定的VM参数来初始化另一个Java项目。根据exec:java的介绍,它们仅接受参数,而不接受VMarguments,因此我的问题是如何从命令行启动具有特定VMarguments的Java项目?谢谢 问题答案: 如果使用Maven的exec:java插件,则无法提供额外的VM参数,因为它在同一VM中运行(即,它已经被初始化)。您将需要使用e

  • 我正在使用Netbean 8.2(虽然这个问题在以前的版本中一直存在)。我可以创建一个maven项目,将以前的项目剪切并传递到该项目中,然后构建该项目并运行它,没有问题。 但是,当我关闭netbeans时,maven项目变成了java项目,我能找到的唯一修复方法是创建一个新的maven项目,并重复剪切和保存。 必须有一个更好的解决方案,如果有人有类似的问题,并解决了它,请让我知道! 非常感谢您的帮