Разбор на командния ред с CLI на Apache Commons

От време на време откривам, че се нуждая от обработка на аргументи от командния ред в Java или за приложения, базирани на Java, или за реализации на main () функции, които осигуряват прост механизъм за тестване директно в тествания клас. Разработчикът на Java има много възможности за разбор на командния ред. Когато има само един, два или малък брой аргументи от командния ред (особено ако наличието или отсъствието на флаг е всичко, което е необходимо, а не придружаваща стойност), напишете няколко реда код, за да обработите тези команди- опция линия не е голяма работа. Когато има повече опции и / или някои опции имат стойности, е хубаво да получите достъп до по-сложна поддръжка за синтактичен анализ на командния ред.

В този запис в блога ще разгледам използването на библиотеката на CLI на Apache Commons, но има много други възможности като args4j, разбор на командния ред на TE-Code, CLAJR (аргументи от командния ред с Java Reflection), JArgs, JSAP (Java Simple Argument Processor) и няколко други (дори повече тук).

Въпреки че библиотеката на Apache Commons CLI е част от Apache Commons, тя е отделно (JAR) изтегляне от изтеглянето на JAR за Apache Commons Modeler и от изтеглянето на JAR за Apache Commons Lang, за което говорих в предишни записи в блога, налични тук и тук. За този запис в блога използвам CLI 1.1, тъй като няма очаквано издание за CLI 2.0 (повече подробности за това в края на този запис).

Ще демонстрирам някои много прости примери за Apache Common CLI и ще включа някои връзки към други ресурси за използването на тази библиотека.

Два важни класа, използващи Apache Common CLI, са класът org.apache.commons.cli.Option и тясно свързаният org.apache.commons.cli.Options (съдържа множество екземпляри на Optionкласа). Тези класове се използват за представяне на очакваните опции на командния ред. Следващите два кодови фрагмента демонстрират настройка на клас Options за опции в стил Posix и опции в стил GNU.

Използване на класа Options с множество екземпляри на опции

 /** * 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; } 

Забележете в примерите за настройка на Опции, че все още няма разлика в боравенето с опциите в стил Posix спрямо опциите в стил GNU. Засега опциите могат да бъдат третирани по същия начин.

Преди да преминете към демонстриране на синтактичен анализ на аргументите на командния ред на CLI въз основа на тези очаквани опции, заслужава да се отбележи поддръжката на CLI за информация за употреба и помощна информация чрез класа org.apache.commons.cli.HelpFormatter. Този полезен клас полезност съдържа методи като претоварени версии на printHelp, претоварени версии на printUsage и няколко други изходни и свързани методи.

Следният кодов фрагмент демонстрира метод, който използва един от методите printUsage на HelpFormatter и един от методите printHelp на този клас.

printUsage () и 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(); } 

Следващият кодов фрагмент показва някои извиквания на методите printHelp () и printUsage (), показани по-горе, и е последван от моментна снимка на екрана, показваща изхода от тяхното изпълнение.

 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); 

Първата моментна снимка на екрана показва резултатите, когато горният код се изпълнява точно както е показано (с trueпредадено на двете приложения на printHelpметода, за да се посочи, че опциите трябва да бъдат включени в частта за използване). Снимката на втория екран показва какво се случва, когато второто повикване до printHelpе преминало фалшиво към него, така че опциите не се показват.

printUsage и printHelp

printUsage и printHelp с One printHelp Не се показват опции

Докато информацията за използването и помощта за опциите е, както подсказват имената им, полезна и полезна, истинската причина за използване на аргументи от командния ред обикновено е да се контролира поведението на приложението. Следващият списък с кодове показва два метода за синтактичен анализ на аргументите в командния ред в стил GNU и Posix. Докато настройването на Опциите не се интересуваше от конкретния стил, освен посочването на самите опции, видът на опцията е важен сега за определяне на подходящия парсер, който да се използва.

usePosixParser () и 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() ); } } 

Когато горният код се изпълни, изходът му изглежда като този, показан в следващите две екранни снимки:

Резултати от PosixParser

Резултати от GNU Parser

Пълният пример

Пълният код за примерното приложение, от което са показани части по-горе, сега е изброен за удобство.