How do I parse command line arguments in Java?

回眸只為那壹抹淺笑 提交于 2019-11-25 23:58:04

问题


What is a good way of parsing command line arguments in Java?


回答1:


Check these out:

  • http://commons.apache.org/cli/
  • http://www.martiansoftware.com/jsap/

Or roll your own:

  • http://docs.oracle.com/javase/7/docs/api/java/util/Scanner.html

For instance, this is how you use commons-cli to parse 2 string arguments:

import org.apache.commons.cli.*;

public class Main {


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

        Options options = new Options();

        Option input = new Option("i", "input", true, "input file path");
        input.setRequired(true);
        options.addOption(input);

        Option output = new Option("o", "output", true, "output file");
        output.setRequired(true);
        options.addOption(output);

        CommandLineParser parser = new DefaultParser();
        HelpFormatter formatter = new HelpFormatter();
        CommandLine cmd;

        try {
            cmd = parser.parse(options, args);
        } catch (ParseException e) {
            System.out.println(e.getMessage());
            formatter.printHelp("utility-name", options);

            System.exit(1);
        }

        String inputFilePath = cmd.getOptionValue("input");
        String outputFilePath = cmd.getOptionValue("output");

        System.out.println(inputFilePath);
        System.out.println(outputFilePath);

    }

}

usage from command line:

$> java -jar target/my-utility.jar -i asd                                                                                       
Missing required option: o

usage: utility-name
 -i,--input <arg>    input file path
 -o,--output <arg>   output file



回答2:


Take a look at the more recent JCommander.

I created it. I’m happy to receive questions or feature requests.




回答3:


I have been trying to maintain a list of Java CLI parsers.

  • Airline
    • Active Fork: https://github.com/rvesse/airline
  • argparse4j
  • argparser
  • args4j
  • clajr
  • cli-parser
  • CmdLn
  • Commandline
  • DocOpt.java
  • dolphin getopt
  • DPML CLI (Jakarta Commons CLI2 fork)
  • Dr. Matthias Laux
  • Jakarta Commons CLI
  • jargo
  • jargp
  • jargs
  • java-getopt
  • jbock
  • JCLAP
  • jcmdline
  • jcommander
  • jcommando
  • jewelcli (written by me)
  • JOpt simple
  • jsap
  • naturalcli
  • Object Mentor CLI article (more about refactoring and TDD)
  • parse-cmd
  • ritopt
  • Rop
  • TE-Code Command
  • picocli has ANSI colorized usage help and autocomplete



回答4:


I've used JOpt and found it quite handy: http://jopt-simple.sourceforge.net/

The front page also provides a list of about 8 alternative libraries, check them out and pick the one that most suits your needs.




回答5:


Someone pointed me to args4j lately which is annotation based. I really like it!




回答6:


It is 2019, time to do better than Commons CLI... :-)

Buy or build?

Many small utility-like applications probably roll their own command line parsing to avoid the additional external dependency.

picocli may be interesting. It is designed to be included as source as a simpler alternative to shading jars into an uberjar.

Another feature you may like is its colorized usage help.

Parser features:

  • Annotation based: parsing is one line of code
  • Strongly typed everything - command line options as well as positional parameters
  • POSIX clustered short options (<command> -xvfInputFile as well as <command> -x -v -f InputFile)
  • An arity model that allows a minimum, maximum and variable number of parameters, e.g, "1..*", "3..5"
  • Subcommands (can be nested to arbitrary depth)
  • Works with Java 5 and higher

The usage help message is easy to customize with annotations (without programming). For example:

(source)

I couldn't resist adding one more screenshot to show what usage help messages are possible. Usage help is the face of your application, so be creative and have fun!

Disclaimer: I created picocli. Feedback or questions very welcome.




回答7:


This is Google's command line parsing library open-sourced as part of the Bazel project. Personally I think it's the best one out there, and far easier than Apache CLI.

https://github.com/pcj/google-options

Installation

Bazel

maven_jar(
    name = "com_github_pcj_google_options",
    artifact = "com.github.pcj:google-options:jar:1.0.0",
    sha1 = "85d54fe6771e5ff0d54827b0a3315c3e12fdd0c7",
)

Gradle

dependencies {
  compile 'com.github.pcj:google-options:1.0.0'
}

Maven

<dependency>
  <groupId>com.github.pcj</groupId>
  <artifactId>google-options</artifactId>
  <version>1.0.0</version>
</dependency>

Usage

Create a class that extends OptionsBase and defines your @Option(s).

package example;

import com.google.devtools.common.options.Option;
import com.google.devtools.common.options.OptionsBase;

import java.util.List;

/**
 * Command-line options definition for example server.
 */
public class ServerOptions extends OptionsBase {

  @Option(
      name = "help",
      abbrev = 'h',
      help = "Prints usage info.",
      defaultValue = "true"
    )
  public boolean help;

  @Option(
      name = "host",
      abbrev = 'o',
      help = "The server host.",
      category = "startup",
      defaultValue = ""
  )
  public String host;

  @Option(
    name = "port",
    abbrev = 'p',
    help = "The server port.",
    category = "startup",
    defaultValue = "8080"
    )
    public int port;

  @Option(
    name = "dir",
    abbrev = 'd',
    help = "Name of directory to serve static files.",
    category = "startup",
    allowMultiple = true,
    defaultValue = ""
    )
    public List<String> dirs;

}

Parse the arguments and use them.

package example;

import com.google.devtools.common.options.OptionsParser;
import java.util.Collections;

public class Server {

  public static void main(String[] args) {
    OptionsParser parser = OptionsParser.newOptionsParser(ServerOptions.class);
    parser.parseAndExitUponError(args);
    ServerOptions options = parser.getOptions(ServerOptions.class);
    if (options.host.isEmpty() || options.port < 0 || options.dirs.isEmpty()) {
      printUsage(parser);
      return;
    }

    System.out.format("Starting server at %s:%d...\n", options.host, options.port);
    for (String dirname : options.dirs) {
      System.out.format("\\--> Serving static files at <%s>\n", dirname);
    }
  }

  private static void printUsage(OptionsParser parser) {
    System.out.println("Usage: java -jar server.jar OPTIONS");
    System.out.println(parser.describeOptions(Collections.<String, String>emptyMap(),
                                              OptionsParser.HelpVerbosity.LONG));
  }

}

https://github.com/pcj/google-options




回答8:


Take a look at the Commons CLI project, lots of good stuff in there.




回答9:


Yeap.

I think you're looking for something like this: http://commons.apache.org/cli

The Apache Commons CLI library provides an API for processing command line interfaces.




回答10:


Maybe these

  • JArgs command line option parsing suite for Java - this tiny project provides a convenient, compact, pre-packaged and comprehensively documented suite of command line option parsers for the use of Java programmers. Initially, parsing compatible with GNU-style 'getopt' is provided.

  • ritopt, The Ultimate Options Parser for Java - Although, several command line option standards have been preposed, ritopt follows the conventions prescribed in the opt package.




回答11:


You might find this meta-article of unhappiness interesting as a jumping off point:

http://furiouspurpose.blogspot.com/2008/07/command-line-parsing-libraries-for-java.html




回答12:


I wrote another one: http://argparse4j.sourceforge.net/

Argparse4j is a command line argument parser library for Java, based on Python's argparse.




回答13:


If you are familiar with gnu getopt, there is a Java port at: http://www.urbanophile.com/arenn/hacking/download.htm.

There appears to be a some classes that do this:

  • http://docs.sun.com/source/816-5618-10/netscape/ldap/util/GetOpt.html
  • http://xml.apache.org/xalan-j/apidocs/org/apache/xalan/xsltc/cmdline/getopt/GetOpt.html



回答14:


airline @ Github looks good. It is based on annotation and is trying to emulate Git command line structures.




回答15:


I know most people here are going to find 10 million reasons why they dislike my way, but nevermind. I like to keep things simple, so I just separate the key from the value using a '=' and store them in a HashMap like this:

Map<String, String> argsMap = new HashMap<>();
for (String arg: args) {
    String[] parts = arg.split("=");
    argsMap.put(parts[0], parts[1]);
} 

You could always maintain a list with the arguments you are expecting, to help the user in case he forgot an argument or used a wrong one... However, if you want too many features this solution is not for you anyway.




回答16:


I wouldn't recommend using Apache Common CLI library, as it is non-threadsafe. It uses stateful classes with static variables and methods to do internal work (e.g. OptionBuilder) and should only be used in single-threaded strongly controlled situations.




回答17:


If you want something lightweight (jar size ~ 20 kb) and simple to use, you can try argument-parser. It can be used in most of the use cases, supports specifying arrays in the argument and has no dependency on any other library. It works for Java 1.5 or above. Below excerpt shows an example on how to use it:

public static void main(String[] args) {
    String usage = "--day|-d day --mon|-m month [--year|-y year][--dir|-ds directoriesToSearch]";
    ArgumentParser argParser = new ArgumentParser(usage, InputData.class);
    InputData inputData = (InputData) argParser.parse(args);
    showData(inputData);

    new StatsGenerator().generateStats(inputData);
}

More examples can be found here




回答18:


Argparse4j is best I have found. It mimics Python's argparse libary which is very convenient and powerful.




回答19:


If you are already using Spring Boot, argument parsing comes out of the box.

If you want to run something after startup, implement the ApplicationRunner interface:

@SpringBootApplication
public class Application implements ApplicationRunner {

  public static void main(String[] args) {
    SpringApplication.run(Application.class, args);
  }

  @Override
  public void run(ApplicationArguments args) {
    args.containsOption("my-flag-option"); // test if --my-flag-option was set
    args.getOptionValues("my-option");     // returns values of --my-option=value1 --my-option=value2 
    args.getOptionNames();                 // returns a list of all available options
    // do something with your args
  }
}

Your run method will be invoked after the context has started up successfully.

If you need access to the arguments before you fire up your application context, you can just simply parse the application arguments manually:

@SpringBootApplication
public class Application implements ApplicationRunner {

  public static void main(String[] args) {
    ApplicationArguments arguments = new DefaultApplicationArguments(args);
    // do whatever you like with your arguments
    // see above ...
    SpringApplication.run(Application.class, args);
  }

}

And finally, if you need access to your arguments in a bean, just inject the ApplicationArguments:

@Component
public class MyBean {

   @Autowired
   private ApplicationArguments arguments;

   // ...
}



回答20:


As one of the comments mentioned earlier (https://github.com/pcj/google-options) would be a good choice to start with.

One thing I want to add-on is:

1) If you run into some parser reflection error, please try use a newer version of the guava. in my case:

maven_jar(
    name = "com_google_guava_guava",
    artifact = "com.google.guava:guava:19.0",
    server = "maven2_server",
)

maven_jar(
    name = "com_github_pcj_google_options",
    artifact = "com.github.pcj:google-options:jar:1.0.0",
    server = "maven2_server",
)

maven_server(
    name = "maven2_server",
    url = "http://central.maven.org/maven2/",
)

2) When running the commandline:

bazel run path/to/your:project -- --var1 something --var2 something -v something

3) When you need the usage help, just type:

bazel run path/to/your:project -- --help



回答21:


For Spring users, we should mention also https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/core/env/SimpleCommandLinePropertySource.html and his twin brother https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/core/env/JOptCommandLinePropertySource.html (JOpt implementation of the same functionality). The advantage in Spring is that you can directly bind the command line arguments to attributes, there is an example here https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/core/env/CommandLinePropertySource.html



来源:https://stackoverflow.com/questions/367706/how-do-i-parse-command-line-arguments-in-java

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!