【问题标题】:Java command line arguments in --key=value format--key=value 格式的 Java 命令行参数
【发布时间】:2014-01-24 00:53:02
【问题描述】:

是否有一种智能/简单的方法来使用 --key=value 格式的命令行参数?我只是快速地检查了 args[i] 以查看它是否包含我的一个键,然后获取该键的值并为其设置一个变量,但必须有更好的方法。我似乎无法通过谷歌搜索找到任何好的东西,所以我一定是在搜索错误的东西。有什么想法/见解?

谢谢!

【问题讨论】:

  • 我个人最喜欢的用于解析命令行参数的工具包是JCommander - 它是配置的注释和feature rich。但实际上有成千上万的命令行解析器......谷歌会是比 StackOverflow 更好的选择。
  • 试试this,但不能保证。
  • 这个是最好的库:pholser.github.io/jopt-simple
  • @user2684301 不要使用“最佳”之类的词,因为它们是规范的。这可能是您的个人喜好,但这并不意味着它是“最好的”。 OP 为什么要使用它?是否符合要求?
  • 当然。 jopt-simple 满足要求。我相信它比其他类似的库(如 apache cli)具有更干净、更安全的 API。查看示例代码,看看您是否有同感。

标签: java command-line


【解决方案1】:

尝试-D 选项,允许设置key=value 对:

运行命令;注意-Dkey之间没有空格

  • java -Dday=Friday -Dmonth=Jan MainClass

在您的代码中:

String day = System.getProperty("day");
String month = System.getProperty("month");

【讨论】:

  • 如果没有设置键则返回空值
【解决方案2】:

到目前为止,还没有办法将--key=value 转换为 Map 而不是 String。

public static void main(String[] args) {

    HashMap<String, String> params = convertToKeyValuePair(args);

    params.forEach((k, v) -> System.out.println("Key : " + k + " Value : " + v));

}

private static HashMap<String, String> convertToKeyValuePair(String[] args) {

    HashMap<String, String> params = new HashMap<>();

    for (String arg: args) {

        String[] splitFromEqual = arg.split("=");

        String key = splitFromEqual[0].substring(2);
        String value = splitFromEqual[1];

        params.put(key, value);

    }

    return params;
}

希望这会有所帮助!

【讨论】:

  • 如果它们本身包含等号,这将默默地使用错误值。例如。 --options=foo=bar,baz=moo 变为 {options=foo}split 的另一个使用不当。
  • 根据您的要求,您可以更改分割字符以避免此类错误。
【解决方案3】:

这会将带有 key=value 对的 String[] args 转换为 Map。此处使用HashMap,因为它允许空值。

package org.company;

import java.util.HashMap;
import java.util.Map;

public class Main {
    /**
     * Convert an array of key=value pairs into a hashmap.
     * The string "key=" maps key onto "", while just "key" maps key onto null.
     * The value may contain '=' characters, only the first "=" is a delimiter.
     * @param args command-line arguments in the key=value format (or just key= or key)
     * @param defaults a map of default values, may be null. Mappings to null are not copied to the resulting map.
     * @param allowedKeys if not null, the keys not present in this map cause an exception (and keys mapped to null are ok)
     * @return a map that maps these keys onto the corresponding values.
     */
    static private HashMap<String, String> _parseArgs(String[] args, HashMap<String, String> defaults, HashMap<String, String> allowedKeys) {
        // HashMap allows null values
        HashMap<String, String> res = new HashMap<>();
        if (defaults != null) {
            for (Map.Entry<String, String> e : defaults.entrySet()) {
                if (e.getValue() != null) {
                    res.put(e.getKey(),e.getValue());
                }
            }
        }
        for (String s: args) {
            String[] kv = s.split("=", 2);
            if (allowedKeys != null && !allowedKeys.containsKey(kv[0])) {
                throw new RuntimeException("the key "+kv[0]+" is not in allowedKeys");
            }
            res.put(kv[0], kv.length<2 ? null : kv[1]);
        }
        return res;
    }

    /**
     * Compose a map to serve as defaults and/or allowedKeys for _parseArgs().
     * The string "key=" maps key onto "" that becomes the default value for the key,
     * while just "key" maps key onto null which makes it a valid key without any default value.
     * The value may contain '=' characters, only the first "=" is a delimiter.
     * @param args Strings in "key=value" (or "key=", or just "key") format.
     * @return a map that maps these keys onto the corresponding values.
     */
    static public HashMap<String, String> defaultArgs(String... args) {
        return _parseArgs(args, null, null);
    }

    /**
     * Convert an array of strings in the "key=value" format to a map.
     * If defaults is not null, the keys not present in this map cause an exception (and keys mapped to null are ok).
     * @param args the array that main(String[]) received
     * @param defaults specifies valid keys and their default values (keys mapped to null are valid, but have no default value)
     * @return a map that maps these keys onto the corresponding values.
     */
    static public HashMap<String, String> mapOfArgs(String[] args, HashMap<String, String> defaults) {
        return _parseArgs(args, defaults, defaults);
    }
    /**
     * Convert an array of strings in the "key=value" format to a map.
     * The keys not present in defaults are always ok.
     * @param args the array that main(String[]) received
     * @param defaults if not null, specifies default values for keys (keys mapped to null are ignored)
     * @return a map that maps these keys onto the corresponding values.
     */
    static public HashMap<String, String> uncheckedMapOfArgs(String[] args, HashMap<String, String> defaults) {
        return _parseArgs(args, defaults, null);
    }

    /**
     * Test harness
     * @param args
     */
    public static void main(String[] args) {
        Map<String, String> argMap = mapOfArgs(args, defaultArgs("what=hello","who=world","print"));
        for (Map.Entry<String,String> e : argMap.entrySet()) {
            System.out.println(""+e.getKey()+" => "+e.getValue()+";");
        }
    }

}

示例运行:

$ java org.company.Main 
what => hello;
who => world;
$ java org.company.Main print=x=y
print => x=y;
what => hello;
who => world;
$ java org.company.Main who=lambdas what=rule print
print => null;
what => rule;
who => lambdas;
$ java org.company.Main who=lambdas what=rule print=
print => ;
what => rule;
who => lambdas;
$ java org.company.Main get
Exception in thread "main" java.lang.RuntimeException: the key get is not in allowedKeys
    at org.company.Main._parseArgs(Main.java:37)
    at org.company.Main.mapOfArgs(Main.java:64)
    at org.company.Main.main(Main.java:9)

上面,发生了异常,因为默认值中没有"get"

如果我们使用uncheckedMapOfArgs() 而不是mapOfArgs()

$ java org.company.Main get
what => hello;
get => null;
who => world;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-06-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-31
    • 2010-10-17
    相关资源
    最近更新 更多