Parsing baris perintah dengan Apache Commons CLI

Dari waktu ke waktu, saya merasa perlu menangani argumen baris perintah di Java baik untuk aplikasi berbasis Java atau untuk implementasi fungsi main () yang menyediakan mekanisme pengujian sederhana langsung di dalam kelas yang diuji. Pengembang Java memiliki banyak pilihan untuk penguraian baris perintah. Jika hanya ada satu, dua, atau sejumlah kecil argumen baris perintah (terutama jika hanya ada atau tidaknya sebuah bendera yang diperlukan daripada nilai yang menyertainya), tulis beberapa baris kode untuk memproses perintah- opsi garis bukanlah masalah besar. Jika ada lebih banyak opsi dan / atau beberapa opsi memiliki nilai, sebaiknya Anda mengakses dukungan yang lebih canggih untuk penguraian baris perintah.

Dalam entri blog ini, saya akan melihat menggunakan pustaka CLI Apache Commons, tetapi ada banyak pilihan lain seperti args4j, parsing baris perintah TE-Code, CLAJR (Argumen Baris Perintah dengan Java Refleksi), JArgs, JSAP (Java Simple Argument Processor), dan beberapa lainnya (bahkan lebih di sini).

Meskipun pustaka CLI Apache Commons adalah bagian dari Apache Commons, ini adalah unduhan (JAR) terpisah dari unduhan JAR untuk Pemodel Apache Commons dan dari unduhan JAR untuk Apache Commons Lang yang saya bicarakan di entri blog sebelumnya tersedia di sini dan di sini. Untuk entri blog ini, saya menggunakan CLI 1.1 karena tidak ada rilis yang diantisipasi untuk CLI 2.0 (detail lebih lanjut tentang ini di akhir entri ini).

Saya akan mendemonstrasikan beberapa contoh Apache Common CLI yang sangat sederhana dan menyertakan beberapa tautan ke sumber daya lain untuk penggunaan pustaka ini.

Dua kelas penting dalam penggunaan Apache Common CLI adalah kelas org.apache.commons.cli.Option dan kelas org.apache.commons.cli.Option yang terkait erat (berisi beberapa instance Optionkelas). Kelas-kelas ini digunakan untuk mewakili opsi baris perintah yang diharapkan. Dua potongan kode berikut mendemonstrasikan pengaturan kelas Opsi untuk opsi gaya Posix dan opsi gaya GNU.

Menggunakan Kelas Opsi dengan Beberapa Contoh Opsi

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

Perhatikan dalam contoh pengaturan Opsi bahwa belum ada perbedaan dalam penanganan opsi gaya Posix versus gaya GNU. Sejauh ini, opsinya dapat diperlakukan sama.

Sebelum beralih ke mendemonstrasikan penguraian argumen baris perintah CLI berdasarkan opsi yang diantisipasi ini, perlu diperhatikan dukungan CLI untuk informasi penggunaan dan informasi bantuan melalui kelas org.apache.commons.cli.HelpFormatter. Kelas utilitas yang berguna ini berisi metode seperti versi printHelp yang kelebihan beban, versi printUsage yang kelebihan beban, dan beberapa metode keluaran dan terkait lainnya.

Potongan kode berikut menunjukkan metode yang menggunakan salah satu metode printUsage HelpFormatter dan salah satu metode printHelp kelas itu.

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

Potongan kode berikutnya menunjukkan beberapa panggilan ke metode printHelp () dan printUsage () yang ditunjukkan di atas dan diikuti oleh snapshot layar yang menunjukkan keluaran dari menjalankannya.

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

Cuplikan layar pertama menunjukkan hasil ketika kode di atas dijalankan persis seperti yang ditunjukkan (dengan truediteruskan ke kedua penggunaan printHelpmetode untuk menunjukkan bahwa opsi harus disertakan dalam porsi penggunaan). Cuplikan layar kedua menunjukkan apa yang terjadi jika panggilan kedua ke printHelptelah salah diteruskan ke sana sehingga opsi tidak ditampilkan.

printUsage dan printHelp

printUsage and printHelp with One printHelp Not Menampilkan Pilihan

Meskipun informasi penggunaan dan bantuan tentang opsi, seperti yang disiratkan namanya, berguna dan berguna, alasan sebenarnya untuk menggunakan argumen baris perintah biasanya untuk mengontrol perilaku aplikasi. Daftar kode berikutnya menunjukkan dua metode untuk mengurai argumen baris perintah gaya GNU dan gaya Posix. Meskipun pengaturan Opsi tidak peduli tentang gaya tertentu selain menentukan opsi itu sendiri, jenis opsi sekarang penting untuk menentukan parser yang sesuai untuk digunakan.

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

Ketika kode di atas dijalankan, outputnya terlihat seperti yang ditunjukkan pada dua snapshot layar berikutnya:

Hasil PosixParser

Hasil Parser GNU

Contoh Lengkap

Kode lengkap untuk aplikasi contoh yang bagiannya ditunjukkan di atas sekarang terdaftar untuk kenyamanan.