Monday, September 11, 2017

How to parse command line arguments in Java

Sometimes we need a simple parser of command line options. Here is a simple example how such a parser can be implemented in Java:


import java.util.HashMap;
import java.util.Map;
public class CommandLine {
public static Parameters parse(String[] args) {
Parameters params = new Parameters();
int i = 0;
while (i < args.length) {
switch(args[i]) {
case "--host":
if (i == args.length - 1) {
throw new RuntimeException("No path specified for --host option");
}
params.add("host", args[++i]);
break;
case "--port":
if (i == args.length - 1) {
throw new RuntimeException("No path specified for --port option");
}
params.add("port", Integer.parseInt(args[++i]));
break;
case "--verbose":
params.add("verbose", Boolean.TRUE);
break;
default:
throw new RuntimeException("Unexpected parameter: " + args[i]);
}
i++;
}
return params;
}
public static class Parameters {
private final Map<String, Object> params = new HashMap<>();
public void add(String name, Object value) {
params.put(name, value);
}
public String getString(String name, String defaultValue) {
Object value = params.get(name);
if (value == null) {
return defaultValue;
}
if (value instanceof String) {
return (String) value;
}
throw new RuntimeException(
String.format("'%s' doesn't look like a string: %s", name, value));
}
public int getInteger(String name, int defaultValue) {
Object value = params.get(name);
if (value == null) {
return defaultValue;
}
if (value instanceof Integer) {
return (Integer) value;
}
throw new RuntimeException(
String.format("'%s' doesn't look like an integer: %s", name, value));
}
public boolean getBoolean(String name, boolean defaultValue) {
Object value = params.get(name);
if (value == null) {
return defaultValue;
}
if (value instanceof Boolean) {
return (Boolean) value;
}
throw new RuntimeException(
String.format("'%s' doesn't look like an integer: %s", name, value));
}
}
public static void main(String[] args) {
Parameters params = parse(args);
System.out.println("host = " + params.getString("host", "localhost"));
System.out.println("port = " + params.getInteger("port", 80));
System.out.println("verbose = " + params.getBoolean("verbose", false));
}
}
You can add more parameters to the "while" loop. Here is how it can be used:

$ javac -d . CommandLine.java 
$ java CommandLine
host    = localhost
port    = 80
verbose = false
$ java CommandLine --host test
host    = test
port    = 80
verbose = false
$ java CommandLine --host test --port 81
host    = test
port    = 81
verbose = false
$ java CommandLine --host test --port 81 --verbose
host    = test
port    = 81
verbose = true
$ java CommandLine --host test --port 81 --verbose --a
Exception in thread "main" java.lang.RuntimeException: Unexpected parameter: --a
 at CommandLine.parse(CommandLine.java:30)
 at CommandLine.main(CommandLine.java:91)
$ java CommandLine --host test --port
Exception in thread "main" java.lang.RuntimeException: No path specified for --output option
 at CommandLine.parse(CommandLine.java:21)
 at CommandLine.main(CommandLine.java:91)
$ java CommandLine --host test --port
Exception in thread "main" java.lang.RuntimeException: No path specified for --port option
 at CommandLine.parse(CommandLine.java:21)
 at CommandLine.main(CommandLine.java:91)

Enjoy!