如何在Java中处理命令行参数

时间:2012-01-20 15:59:48

标签: java design-patterns

假设我有一个简单的程序,它以下列形式之一接受参数输入
do1 inputLocation outputLocation
do2 inputLocation outputLocation
do3 [30或60或90] inputLocation outputLocation
do4 [P D或C] inputLocation outputLocation
do5 [G H I] inputLocation outputLocation

我还需要在程序中调用5个具有相同名称的函数。到目前为止,我想过这样做(在“半伪代码”中)

static void main(String[] args)
{
    if (args.length == 3)
        processTriple(args);
    if (args.length == 4)
        processQuadruple(args);
    throw new UnsupportedOperationException("dasdhklasdha");
}

过程函数看起来像这样

processDouble(String args[])
{
    String operation = "args[0]";
    Location input = getInput(args[1]);
    Location output = getInput(args[2]);
    if (operation.equals("do1"))
        do1(input,output);
    if (operation.equals("do2"))
        do2(input,output);
    ... etc
}

我这样做的方式似乎不太可扩展。如果一个函数的参数发生了变化,或者添加了新函数,那么这似乎很难维护。 什么是“最好”的方式来做这样的事情

5 个答案:

答案 0 :(得分:10)

此时我会使用commons-clijargs。除非你试图做一些非常特殊的论点,否则我会说你专注于应用程序的真实业务,而不是处理应用程序参数的混乱

答案 1 :(得分:3)

使用命令行解析库。看看here

答案 2 :(得分:2)

我过去曾使用过JOpt Simple,效果很好。它可以让你抽象出命令行arg mess,并保持一个非常干净的可更新参数列表。另一个好处是它将生成标准命令行实用程序所具有的帮助输出。

下面是一个简单的例子:

private void runWithArgs (String[] args) {
    OptionParser parser = getOptionParser ();
    OptionSet options = null;

    try {
        options = parser.parse (args);
    }
    catch (OptionException e) {
        log.error ("Sorry the command line option(s): " + e.options () + 
                    " is/are not recognized. -h for help.");
        return;
    }

    if (options.has ("h")) {
        try {
            log.info ("Help: ");
            parser.printHelpOn (System.out);
        }
        catch (IOException e) {
            log.error ("Trying to print the help screen." + e.toString ());
        }
        return;
    }

    if (options.has ("i")) {
        defaultHost = (String) options.valueOf ("i");
    }

    if (options.has ("p")) {
        defaultPort = (Integer) options.valueOf ("p");
    }

    if (options.has ("q")) {
        String queryString = (String) options.valueOf ("q");

        log.info ("Performing Query: " + queryString);
        performQuery (queryString, defaultHost, defaultPort);
        return;
    }
}

答案 3 :(得分:1)

我之前也使用过args4j成功的结果。

只是另一种选择。

答案 4 :(得分:1)

您可以使用CédricBeust的JCommander

  

因为生命太短而无法解析命令行参数

我甚至创造性地违反了图书馆的原始意图来解析NMEA 0183句子,如 $ GPRTE ,如下所示:

import java.util.List;

import com.beust.jcommander.Parameter;
import com.beust.jcommander.internal.Lists;

public class GPRTE {
    @Parameter
    public List<String> parameters = Lists.newArrayList();

    @Parameter(names = "-GPRTE", arity = 4, description = "GPRTE")
    public List<String> gprte;
}

将NMEA 0183句子 $ GPRTE $GPRTE,1,1,c,*37处理为-GPRTE 1 1 c *37以符合JCommander解析语法的代码段:

/**
 * <b>RTE</b> - route message<p>
 * Processes each <b>RTE</b> message received from the serial port in following format:<p>$GPRTE,d1,d2,d3,d4<p>Example: $GPRTE,1,1,c,*37
 * @param sequences result of {@link #Utils.process(String)} method
 * @see <a href="http://www.gpsinformation.org/dale/nmea.htm#RTE">http://www.gpsinformation.org/dale/nmea.htm#RTE<a><p>*/
public static void processGPRTE(final String command){
    final String NMEA_SENTENCE = "GPRTE";
    final String PARAM = "\u0001";
    final String DOLLAR = "\u0004";
    final String COMMA = "\u0005";

    String parsedString = command;

    if (parsedString.contains("$"+NMEA_SENTENCE)){

        parsedString = parsedString.replaceAll("\\$", DOLLAR+PARAM);
        parsedString = parsedString.replaceAll(",", COMMA);

        System.out.println("GPRTE: " + parsedString);

        String[] splits = parsedString.split(DOLLAR);
        for(String info: splits){

            if (info.contains(PARAM+NMEA_SENTENCE)) {
                info = info.replaceFirst(PARAM, "-");

                System.out.println("GPRTE info: " + info);


                String[] args = info.split(COMMA);

                GPRTE cmd = new GPRTE();
                new JCommander(cmd, processEmptyString(args));
                List<String> message = cmd.gprte;

                String data1 = SerialOutils.unescape(message.get(0));
                System.out.println("GPRTE: data1 = " + data1);

                String data2 = SerialOutils.unescape(message.get(1));
                System.out.println("GPRTE: data2 = " + data2);

                String data3 = SerialOutils.unescape(message.get(2));
                System.out.println("GPRTE: data3 = " + data3);

                String data4 = SerialOutils.unescape(message.get(3));
                System.out.println("GPRTE: data4 = " + data4);

                System.out.println("");

            }
        }
    }
}