Befehlszeilenanalyse mit Apache Commons CLI

Von Zeit zu Zeit muss ich Befehlszeilenargumente in Java entweder für Java-basierte Anwendungen oder für Implementierungen von main () - Funktionen verarbeiten, die einen einfachen Testmechanismus direkt in der zu testenden Klasse bieten. Der Java-Entwickler hat viele Möglichkeiten zum Parsen von Befehlszeilen. Wenn nur ein, zwei oder eine kleine Anzahl von Befehlszeilenargumenten vorhanden sind (insbesondere wenn nur das Vorhandensein oder Fehlen eines Flags anstelle eines zugehörigen Werts erforderlich ist), schreiben Sie einige Codezeilen, um diese Befehlsargumente zu verarbeiten. Linienoptionen sind keine große Sache. Wenn es mehr Optionen gibt und / oder einige Optionen Werte haben, ist es hilfreich, auf eine komplexere Unterstützung für die Befehlszeilenanalyse zuzugreifen.

In diesem Blogeintrag werde ich mich mit der Verwendung der Apache Commons CLI-Bibliothek befassen, aber es gibt zahlreiche andere Möglichkeiten, wie z. B. args4j, TE-Code-Befehlszeilenanalyse, CLAJR (Befehlszeilenargumente mit Java-Reflexion), JArgs, JSAP (Java Simple) Argument Processor) und einige andere (noch mehr hier).

Obwohl die Apache Commons CLI-Bibliothek Teil von Apache Commons ist, handelt es sich um einen separaten (JAR-) Download vom JAR-Download für Apache Commons Modeler und vom JAR-Download für Apache Commons Lang, über den ich in früheren Blogeinträgen gesprochen habe, die hier und hier verfügbar sind. Für diesen Blogeintrag verwende ich CLI 1.1, da für CLI 2.0 keine Veröffentlichung geplant ist (weitere Details hierzu am Ende dieses Eintrags).

Ich werde einige sehr einfache Beispiele für Apache Common CLI demonstrieren und einige Links zu anderen Ressourcen zur Verwendung dieser Bibliothek einfügen.

Zwei wichtige Klassen, die Apache Common CLI verwenden, sind die Klasse org.apache.commons.cli.Option und die eng verwandte Klasse org.apache.commons.cli.Options (enthält mehrere Instanzen der OptionKlasse). Diese Klassen werden verwendet, um die erwarteten Befehlszeilenoptionen darzustellen. Die folgenden zwei Codefragmente veranschaulichen das Einrichten einer Optionsklasse für Optionen im Posix-Stil und Optionen im GNU-Stil.

Verwenden der Optionsklasse mit mehreren Optionsinstanzen

 /** * Construct and provide Posix-compatible Options. * * @return Options expected from command-line of Posix form. */ public static Options constructPosixOptions() { final Options posixOptions = new Options(); posixOptions.addOption("display", false, "Display the state."); return posixOptions; } /** * Construct and provide GNU-compatible Options. * * @return Options expected from command-line of GNU form. */ public static Options constructGnuOptions() { final Options gnuOptions = new Options(); gnuOptions.addOption("p", "print", false, "Option for printing") .addOption("g", "gui", false, "HMI option") .addOption("n", true, "Number of copies"); return gnuOptions; } 

Beachten Sie in den Beispielen zum Einrichten von Optionen, dass es noch keinen Unterschied in der Behandlung von Optionen im Posix-Stil im Vergleich zu Optionen im GNU-Stil gibt. Bisher können die Optionen gleich behandelt werden.

Bevor Sie das Parsen von Befehlszeilenargumenten durch CLI anhand dieser erwarteten Optionen demonstrieren, sollten Sie die Unterstützung von CLI für Nutzungsinformationen und Hilfeinformationen über die Klasse org.apache.commons.cli.HelpFormatter beachten. Diese nützliche Dienstprogrammklasse enthält Methoden wie überladene Versionen von printHelp, überladene Versionen von printUsage und verschiedene andere Ausgabe- und verwandte Methoden.

Das folgende Codefragment zeigt eine Methode, die eine der printUsage-Methoden von HelpFormatter und eine der printHelp-Methoden dieser Klasse verwendet.

printUsage () und printHelp ()

 /** * Print usage information to provided OutputStream. * * @param applicationName Name of application to list in usage. * @param options Command-line options to be part of usage. * @param out OutputStream to which to write the usage information. */ public static void printUsage( final String applicationName, final Options options, final OutputStream out) { final PrintWriter writer = new PrintWriter(out); final HelpFormatter usageFormatter = new HelpFormatter(); usageFormatter.printUsage(writer, 80, applicationName, options); writer.close(); } /** * Write "help" to the provided OutputStream. */ public static void printHelp( final Options options, final int printedRowWidth, final String header, final String footer, final int spacesBeforeOption, final int spacesBeforeOptionDescription, final boolean displayUsage, final OutputStream out) { final String commandLineSyntax = "java -cp ApacheCommonsCLI.jar"; final PrintWriter writer = new PrintWriter(out); final HelpFormatter helpFormatter = new HelpFormatter(); helpFormatter.printHelp( writer, printedRowWidth, commandLineSyntax, header, options, spacesBeforeOption, spacesBeforeOptionDescription, footer, displayUsage); writer.close(); } 

Das nächste Code-Snippet zeigt einige Aufrufe der oben gezeigten Methoden printHelp () und printUsage (), gefolgt von einem Screenshot, der die Ausgabe der Ausführung dieser Methoden zeigt.

 System.out.println("-- USAGE --"); printUsage(applicationName + " (Posix)", constructPosixOptions(), System.out); displayBlankLines(1, System.out); printUsage(applicationName + " (Gnu)", constructGnuOptions(), System.out); displayBlankLines(4, System.out); System.out.println("-- HELP --"); printHelp( constructPosixOptions(), 80, "POSIX HELP", "End of POSIX Help", 3, 5, true, System.out); displayBlankLines(1, System.out); printHelp( constructGnuOptions(), 80, "GNU HELP", "End of GNU Help", 5, 3, true, System.out); 

Der erste Screenshot zeigt die Ergebnisse, wenn der obige Code genau wie gezeigt ausgeführt wird (wobei truebeide Verwendungen der printHelpMethode übergeben wurden, um anzugeben, dass Optionen im Verwendungsabschnitt enthalten sein sollten). Der zweite Screenshot zeigt, was passiert, wenn der zweite Anruf an printHelpfalse übergeben wurde, sodass die Optionen nicht angezeigt werden.

printUsage und printHelp

printUsage und printHelp mit einer printHelp ohne Anzeigeoptionen

Während die Verwendungs- und Hilfeinformationen zu den Optionen, wie ihre Namen andeuten, hilfreich und nützlich sind, besteht der eigentliche Grund für die Verwendung von Befehlszeilenargumenten normalerweise darin, das Verhalten der Anwendung zu steuern. Die nächste Codeliste zeigt zwei Methoden zum Parsen von Befehlszeilenargumenten im GNU-Stil und im Posix-Stil. Während sich das Einrichten der Optionen nicht um den spezifischen Stil kümmerte, außer um die Optionen selbst anzugeben, ist der Optionstyp jetzt wichtig, um den geeigneten zu verwendenden Parser zu bestimmen.

usePosixParser () und useGnuParser ()

 /** * Apply Apache Commons CLI PosixParser to command-line arguments. * * @param commandLineArguments Command-line arguments to be processed with * Posix-style parser. */ public static void usePosixParser(final String[] commandLineArguments) { final CommandLineParser cmdLinePosixParser = new PosixParser(); final Options posixOptions = constructPosixOptions(); CommandLine commandLine; try { commandLine = cmdLinePosixParser.parse(posixOptions, commandLineArguments); if ( commandLine.hasOption("display") ) { System.out.println("You want a display!"); } } catch (ParseException parseException) // checked exception { System.err.println( "Encountered exception while parsing using PosixParser:\n" + parseException.getMessage() ); } } /** * Apply Apache Commons CLI GnuParser to command-line arguments. * * @param commandLineArguments Command-line arguments to be processed with * Gnu-style parser. */ public static void useGnuParser(final String[] commandLineArguments) { final CommandLineParser cmdLineGnuParser = new GnuParser(); final Options gnuOptions = constructGnuOptions(); CommandLine commandLine; try { commandLine = cmdLineGnuParser.parse(gnuOptions, commandLineArguments); if ( commandLine.hasOption("p") ) { System.out.println("You want to print (p chosen)!"); } if ( commandLine.hasOption("print") ) { System.out.println("You want to print (print chosen)!"); } if ( commandLine.hasOption('g') ) { System.out.println("You want a GUI!"); } if ( commandLine.hasOption("n") ) { System.out.println( "You selected the number " + commandLine.getOptionValue("n")); } } catch (ParseException parseException) // checked exception { System.err.println( "Encountered exception while parsing using GnuParser:\n" + parseException.getMessage() ); } } 

Wenn der obige Code ausgeführt wird, sieht seine Ausgabe wie in den nächsten beiden Bildschirmschnappschüssen gezeigt aus:

PosixParser Ergebnisse

GNU Parser Ergebnisse

Das vollständige Beispiel

Der vollständige Code für die Beispielanwendung, aus der oben Teile gezeigt wurden, ist jetzt der Einfachheit halber aufgeführt.