Raščlanjivanje naredbenog retka s Apache Commons CLI

S vremena na vrijeme, uvidim kako trebam obraditi argumente naredbenog retka u Javi ili za aplikacije temeljene na Javi ili za implementacije glavne () funkcije koje pružaju jednostavan mehanizam testiranja izravno unutar klase koja se ispituje. Java programer ima mnogo izbora za raščlanjivanje naredbenog retka. Kada postoji samo jedan, dva ili mali broj argumenata naredbenog retka (pogotovo ako je prisutnost ili odsutnost zastave sve što je potrebno, a ne popratna vrijednost), napišite nekoliko redaka koda za obradu ovih naredbenih linijske opcije nisu velika stvar. Kada postoji više opcija i / ili neke opcije imaju vrijednosti, lijepo je pristupiti sofisticiranijoj podršci za raščlanjivanje naredbenog retka.

U ovom članku na blogu osvrnut ću se na upotrebu Apache Commons CLI knjižnice, ali postoje brojni drugi izbori poput args4j, TE-Code raščlanjivanje naredbenog retka, CLAJR (Argumenti naredbenog retka s Java Reflectionom), JArgs, JSAP (Java Simple Argument Processor) i nekoliko drugih (ovdje još više).

Iako je Apache Commons CLI biblioteka dio Apache Commonsa, to je zasebno (JAR) preuzimanje iz JAR-a za Apache Commons Modeler i iz JAR-a za Apache Commons Lang o kojem sam govorio u prethodnim zapisima na blogu dostupnim ovdje i ovdje. Za ovaj unos na blogu koristim CLI 1.1 jer ne postoji predviđeno izdanje za CLI 2.0 (više detalja o tome na kraju ovog unosa).

Pokazat ću nekoliko vrlo jednostavnih primjera Apache Common CLI-a i uključiti neke poveznice na druge resurse o korištenju ove knjižnice.

Dvije važne klase u upotrebi Apache Common CLI-ja su klasa org.apache.commons.cli.Option i usko povezane org.apache.commons.cli.Options (sadrži više primjeraka Optionklase). Te se klase koriste za predstavljanje očekivanih opcija naredbenog retka. Sljedeća dva isječka koda pokazuju postavljanje klase Options za opcije u stilu Posix i GNU.

Korištenje klase opcija s više instanci opcija

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

Primijetite u primjerima postavljanja opcija da još uvijek nema razlike u rukovanju opcijama u stilu Posix u odnosu na GNU. Do sada se opcije mogu tretirati na isti način.

Prije nego što prijeđete na demonstraciju CLI-jevog raščlanjivanja argumenata naredbenog retka na temelju ovih predviđenih opcija, vrijedi napomenuti CLI-jevu podršku za informacije o korištenju i informacije o pomoći putem klase org.apache.commons.cli.HelpFormatter. Ova korisna klasa korisnih programa sadrži metode kao što su preopterećene verzije printHelp, preopterećene verzije printUsage i nekoliko drugih izlaznih i srodnih metoda.

Sljedeći isječak koda prikazuje metodu koja koristi jednu od metoda PrintUsage HelpFormattera i jednu od metoda klase printHelp.

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

Sljedeći isječak koda prikazuje neke pozive gore prikazanim metodama printHelp () i printUsage (), a nakon toga slijedi snimka zaslona koja prikazuje izlaz iz njihovog pokretanja.

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

Prva snimka zaslona prikazuje rezultate kada se gornji kôd izvrši točno onako kako je prikazano (s trueprosljeđivanjem obje upotrebe printHelpmetode kako bi se naznačilo da opcije trebaju biti uključene u dio upotrebe). Snimka drugog zaslona prikazuje što se događa kada mu je drugi poziv na printHelplažno proslijeđen tako da se opcije ne prikazuju.

printUsage i printHelp

printUsage i printHelp s jednim printHelpom opcije se ne prikazuju

Iako su informacije o upotrebi i pomoći o opcijama, kao što njihova imena impliciraju, korisne i korisne, pravi razlog korištenja argumenata naredbenog retka obično je kontrola ponašanja aplikacije. Sljedeći popis kodova prikazuje dvije metode za raščlanjivanje argumenata naredbenog retka u stilu GNU i Posix. Iako postavljanje opcija nije marilo za određeni stil, osim za specificiranje samih opcija, vrsta opcije je sada važna za određivanje odgovarajućeg raščlanjivača koji će se koristiti.

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

Kada se izvrši gornji kôd, njegov izlaz izgleda poput onoga prikazanog u sljedeća dva snimka zaslona:

Rezultati PosixParser

Rezultati GNU raščlanjivača

Cjelovit primjer

Kompletni kôd za primjer aplikacije iz koje su gore prikazani dijelovi sada je naveden radi praktičnosti.