Friday 16 December 2016

Commons CLI: Parsing command line options

One of the main advantage of Commons CLI library is, it provides easy to use APIs to parse command line arguments given to your java application.

Let me explain with an example, suppose you are developing an application ‘FileUpper.java’, where you read an input file and convert all the characters to upper case and write all the upper case characters to output file.

You expect user to call the application in the following way.
java FileUpper -i inputFileName -o outputFileName

-i : Specifies the input
inputFileName : Specifies the input file path
-o : Specifies the output
outputFileName: Specifies the output file path

Following program validates command line arguments passed to FileUpper class.

FileUpper.java
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.DefaultParser;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.Option;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;

public class FileUpper {

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

  Options options = new Options();

  Option input = new Option("i", "input", true, "input file to read data from");
  input.setRequired(true);
  input.setArgName("FILE PATH");
  options.addOption(input);

  Option output = new Option("o", "output", true, "output file to write the final result");
  output.setRequired(true);
  output.setArgName("FILE PATH");
  options.addOption(output);

  CommandLineParser commandLineParser = new DefaultParser();
  HelpFormatter helpFormatter = new HelpFormatter();
  CommandLine commandLine;

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

   System.exit(1);
   return;
  }

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

  System.out.println("Input File Path : " + inputFilePath);
  System.out.println("output File path : " + outputFilePath);

 }

}

Now run the program with proper arguments.
C:\Users\Krishna>java FileUpper -i abc.txt -o out.txt  
Input File Path : abc.txt
output File path : out.txt

One advantage is, you can change the command arguments order, you can use both short option, long options and combination of both short and long options.

For example, all below combinations work as expected.

java FileUpper -i abc.txt -o out.txt         
java FileUpper -o out.txt -i abc.txt
java FileUpper -o out.txt -input abc.txt
java FileUpper -output out.txt -input abc.txt


Now try to run the FileUpper without command line arguments.
<
C:\Users\Krishna>java FileUpper   
Missing required options: i, o
usage: utility-name
 -i,--input <FILE PATH>    input file to read data from
 -o,--output <FILE PATH>   output file to write the final result


Now run the program with only option -i
C:\Users\Krishna>java FileUpper -i abc.txt  
Missing required option: o
usage: utility-name
 -i,--input <FILE PATH>    input file to read data from
 -o,--output <FILE PATH>   output file to write the final result

Now run the program with only option -o
C:\Users\Krishna>java FileUpper -o out.txt
Missing required option: i
usage: utility-name
 -i,--input <FILE PATH>    input file to read data from
 -o,--output <FILE PATH>   output file to write the final result

Now run the program by not providing the input file (just pass -i argument)
C:\Users\Krishna>java FileUpper -i 
Missing argument for option: i
usage: utility-name
 -i,--input <FILE PATH>    input file to read data from
 -o,--output <FILE PATH>   output file to write the final result


As you see in all the cases commons-CLI api is giving proper error response.

What about optional command line arguments?
If the command line utility has any optional arguments, Command line parser don’t validate them. It validates only compulsory arguments. For example, I am adding ‘lang’ option. You can even run the program with out supplying lang option.


FileUpper.java
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.DefaultParser;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.Option;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;

public class FileUpper {

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

  Options options = new Options();

  Option input = new Option("i", "input", true, "input file to read data from");
  input.setRequired(true);
  input.setArgName("FILE PATH");
  options.addOption(input);

  Option output = new Option("o", "output", true, "output file to write the final result");
  output.setRequired(true);
  output.setArgName("FILE PATH");
  options.addOption(output);
  
  Option language = new Option("lang", "language", true, "Encoding Langauge");
  language.setArgName("LANGUAGE");
  options.addOption(language);

  CommandLineParser commandLineParser = new DefaultParser();
  HelpFormatter helpFormatter = new HelpFormatter();
  CommandLine commandLine;

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

   System.exit(1);
   return;
  }

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

  System.out.println("Input File Path : " + inputFilePath);
  System.out.println("output File path : " + outputFilePath);

 }

}









Previous                                                 Next                                                 Home

No comments:

Post a Comment