Parsing Command-Line Arguments

Problem

You need to parse command-line options. Java doesn’t provide an API for it.

Solution

Look in the args array passed as an argument to main. Or use my GetOpt class.

Discussion

The Unix folk have had to deal with this longer than anybody, and they came up with a C-library function called getopt. [10] getopt processes your command-line arguments and looks for single-character options set off with dashes and optional arguments. For example, the command:

sort -n -o outfile myfile1 yourfile2

runs the standard sort program. The -n tells it that the records are numeric rather than textual, and the -o outfile tells it to write its output into a file named outfile. The remaining words, myfile1 and yourfile2, are treated as the input files to be sorted. On a Microsoft-based platform such as Windows 95, command arguments are set of with slashes ( / ). We will use the Unix form -- a dash -- in our API, but feel free to change the code to use slashes.

As in C, the getopt( ) method is used in a while loop. It returns once for each valid option found, returning the value of the character that was found or zero when all options (if any) have been processed.

Here is a program that uses my GetOpt class just to see if there is a -h (for help) argument on the command line:

import com.darwinsys.util.GetOpt;

/** Trivial demonstration of GetOpt. If -h present, print help.
 */
public class GetOptSimple {
    public static void main(String[] args) {
        GetOpt go = new GetOpt("h");
        char c;
        while ((c = go.getopt(args)) != 0) {
            switch(c) {
            case 'h':
                helpAndExit(0);
                break;
            default:
                System.err.println("Unknown option in " +
                    args[go.getOptInd(  )-1]);
                helpAndExit(1);
            }
        }
        System.out.println(  );
    }

    /** Stub for providing help on usage
     * You can write a longer help than this, certainly.
     */
    static void helpAndExit(int returnValue) {
        System.err.println("This would tell you how to use this program");
        System.exit(returnValue);
    }
}

The following longer demo program has several options:

import com.darwinsys.util.GetOpt;

/** Simple demonstration of GetOpt. Accept the '-n' and '-o outfile'
 * options as shown for sort, and also -h for help.
 */
public class GetOptDemo {
    public static void main(String[] args) {
        GetOpt go = new GetOpt("hno:");
        boolean numeric_option = false;
        String outFileName = "(standard output)";
        char c;
        while ((c = go.getopt(args)) != GetOpt.DONE) {
            switch(c) {
            case 'h':
                doHelp(0);
                break;
            case 'n':
                numeric_option = true;
                break;
            case 'o':
                outFileName = go.optarg(  );
                break;
            default:
                System.err.println("Unknown option character " + c);
                doHelp(1);
            }
        }
        System.out.print("Options: ");
        System.out.print("Numeric: " + numeric_option + ' '),
        System.out.print("Output: " + outFileName + "; ");
        System.out.println("Inputs: ");
        if (go.getOptInd(  )-1 == args.length) {
            doFile("(standard input)");
        } else for (int i=go.getOptInd(  )-1; i<args.length; i++)
            doFile(args[i]);
    }

    /** Stub for providing help on usage
     * You can write a longer help than this, certainly.
     */
    static void doHelp(int returnValue) {
        System.err.println("Usage: GetOptDemo [-h][-n][-o outfile] file ...");
        System.exit(returnValue);
    }

    /** Stub to demonstrate processine one file. */
    static void doFile(String fileName) {
        System.out.println(fileName + ' '),
    }
}

If we invoke it several times with different options, here’s how it behaves:

C:javasrcenviron>java GetOptDemo
Options: Numeric: false Output: (standard output) ; Input: (standard input)

C:javasrcenviron>java GetOptDemo -h
Usage: GetOptDemo [-h][-n][-o outfile] file ...

C:javasrcenviron>java GetOptDemo -n a b c
Options: Numeric: true Output: (standard output) ; Input: b c

C:javasrcenviron>java GetOptDemo -n -o resultfile file1 file2
Options: Numeric: true Output: resultfile ; Input: file2

Here is a longer example using GetOpt:

public class GetOptTest {
    public static void main(String argv[]) {
        String goodArgChars = "o:h", goodArgs[]  = {
            "-h", "-o", "outfile", "infile"
        };
        String badArgChars = "f1o", badArgs[]  = {
            "-h", "-o", "outfile", "infile"
        };
        process(goodArgChars, goodArgs);
        process(badArgChars, goodArgs);
        process(badArgChars, badArgs);
    }

    /** Private function, for testing. */
    private static void process(String argChars, String[] args) {

        System.out.println("** START ** " + argChars + '(' + args.length + ')'),

        GetOpt go = new GetOpt(argChars);

        char c;
        while ((c = go.getopt(args)) != 0) {
            System.out.print("Found " + c);
            if (go.optarg(  ) != null)
                System.out.print("; Option " + go.optarg(  ));
            System.out.println(  );
        }
        for (int i=go.optind(  ); i<args.length; i++)
            System.out.println("Filename-like arg " + args[i]);
    }
}

This program (which I used to test the GetOpt class while I was writing it) demonstrates several uses of getopt, some successful and some (by design) unsuccessful. It prints the successes and failures as it goes:

$ java GetOptTest
** START ** o:h(4)
Found h
Found o; Option outfile
** START ** f1o(4)
Bad option
Found o
Filename-like arg infile
At least one user error found
** START ** f1o(4)
Bad option
Found o
Filename-like arg infile
At least one user error found 
$

GetOpt is an adequate tool for processing command-line options. You may come up with something better and contribute it to the Java world; this is left as an exercise for the reader.



[10] There are several variations on getopt in the Unix world; my version emulates fairly closely the original AT&T standard one. The newer ones offer more frills such as long-name arguments, but the basic operation is pretty similar.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.118.205.235