Java 命令行界面(第 1 部分):Apache Commons CLI

位置:首页>文章>详情   分类:Java教程   阅读(133)   2023-12-09 16:34:57

虽然我通常使用 Groovy 来编写 JVM 托管的脚本以从命令行运行,但有时我需要在 Java 应用程序中解析命令行参数并且有大量可用的库供 Java 开发人员用来解析命令行参数。在本文中,我介绍了这些 Java 命令行解析库中最著名的一个:Apache Commons CLI

之前在 Apache Commons CLI 上写过博客,但那篇文章已有八年多了,它描述的是 Apache Commons CLI 1.1。我在那篇文章中演示的两个类 GnuParserPosixParser 已被弃用。当前帖子中的示例基于 Apache Commons CLI 1.4 并使用 CLI 1.3 引入的更新的 DefaultParser 来替换 GnuParserPosixParser

Apache Commons CLI 文档的“简介”解释了 Commons CLI 如何完成“命令行处理的三个阶段”(“定义”、“解析”和“询问”)。这三个阶段在 Commons CLI 中映射到类 OptionOptions(“定义”)、接口 CommandLineParser(“解析”),以及CommandLine 类(“审讯”)。

对于此处使用 Apache Commons CLI 构建的示例,预期的命令行参数相对简单。一个参数是可选的,当指定时,表示启用详细输出。另一个参数是必需的,用于指定要由虚拟应用程序处理的文件。可选参数没有与标志关联的值,表示为 -v--verbose。必需的参数后应跟一个值,该值是文件的路径和名称。此标志是 -f--file。下一个代码清单演示了使用 Commons CLI 的 Option.Builder(随 Commons CLI 1.3 引入)构建预期选项作为“定义”阶段的一部分。

将 Apache Commons CLI Option.Builder 用于“定义阶段”的示例

/**
 * "Definition" stage of command-line parsing with Apache Commons CLI.
 * @return Definition of command-line options.
 */
private static Options generateOptions()
{
   final Option verboseOption = Option.builder("v")
      .required(false)
      .hasArg(false)
      .longOpt(VERBOSE_OPTION)
      .desc("Print status with verbosity.")
      .build();
   final Option fileOption = Option.builder("f")
      .required()
      .longOpt(FILE_OPTION)
      .hasArg()
      .desc("File to be processed.")
      .build();
   final Options options = new Options();
   options.addOption(verboseOption);
   options.addOption(fileOption);
   return options;
}

如上例所示,为 Apache Commons CLI 实现的“Builder”模式具有构建器模式的优点,例如在一个语句中的完全完成状态,并使用高度可读的构建器方法来设置该实例的各个字段。我的关于 Apache Commons CLI 的较早帖子 演示了使用替代的传统构造函数方法来实例化 Option 实例。

定义命令行选项后,是时候进入“解析”阶段了,下一个代码清单演示了如何通过简单地调用方法 CommandLinePaser.parse() 来使用 Apache Commons CLI 进行解析。

使用 Commons CLI 解析命令行选项

/**
 * "Parsing" stage of command-line processing demonstrated with
 * Apache Commons CLI.
 *
 * @param options Options from "definition" stage.
 * @param commandLineArguments Command-line arguments provided to application.
 * @return Instance of CommandLine as parsed from the provided Options and
 *    command line arguments; may be {@code null} if there is an exception
 *    encountered while attempting to parse the command line options.
 */
private static CommandLine generateCommandLine(
   final Options options, final String[] commandLineArguments)
{
   final CommandLineParser cmdLineParser = new DefaultParser();
   CommandLine commandLine = null;
   try
   {
      commandLine = cmdLineParser.parse(options, commandLineArguments);
   }
   catch (ParseException parseException)
   {
      out.println(
           "ERROR: Unable to parse command-line arguments "
         + Arrays.toString(commandLineArguments) + " due to: "
         + parseException);
   }
   return commandLine;
}

请注意,此代码使用较新版本的 Apache Commons CLI 实例化一个 DefaultParser 来进行解析,而不是 PosxParserGnuParser在旧代码中完成

定义了命令行对象并解析了命令行后,就到了审讯阶段了。下一个代码清单演示了 Apache Commons CLI 对命令行询问的支持。

使用 Commons CLI 查询命令行

final boolean verbose =
   commandLine.hasOption(VERBOSE_OPTION);
final String fileName =
   commandLine.getOptionValue(FILE_OPTION);
out.println("The file '" + fileName + "' was provided and verbosity is set to '" + verbose + "'.");

上面的代码清单演示了使用 CommandLine.hasOption() 来确定选项的特定标志是否存在,而不考虑是否为该标志提供了值(适用于 -v /--verbose 在我们的例子中)。同样,代码显示 CommandLine.getOptionValue() 可用于获取与提供的命令行标志关联的值(适用于 -f/--file 选项在我们的例子中)。

下一个屏幕快照演示了上面显示的代码清单的简单示例的输出,它们演示了对上述冗长和文件路径/位置命令行选项的支持。

第二个屏幕快照演示了当命令行参数不包含必需的命令行参数时 Commons CLI 的输出。

对于任何用于构建 Java 命令行解析的框架来说,一个有用的功能是支持使用和帮助信息的能力。这是通过 Commons CLI 的 HelpFormatter 完成的。下一个代码清单演示了如何使用 HelpFormatter 来打印帮助和用法信息,代码清单后面的屏幕快照演示了使用时帮助和用法的外观。

使用 Commons CLI 获取“usage”和“help”详细信息

/**
 * Generate usage information with Apache Commons CLI.
 *
 * @param options Instance of Options to be used to prepare
 *    usage formatter.
 * @return HelpFormatter instance that can be used to print
 *    usage information.
 */
private static void printUsage(final Options options)
{
   final HelpFormatter formatter = new HelpFormatter();
   final String syntax = "Main";
   out.println("\n=====");
   out.println("USAGE");
   out.println("=====");
   final PrintWriter pw  = new PrintWriter(out);
   formatter.printUsage(pw, 80, syntax, options);
   pw.flush();
}

/**
 * Generate help information with Apache Commons CLI.
 *
 * @param options Instance of Options to be used to prepare
 *    help formatter.
 * @return HelpFormatter instance that can be used to print
 *    help information.
 */
private static void printHelp(final Options options)
{
   final HelpFormatter formatter = new HelpFormatter();
   final String syntax = "Main";
   final String usageHeader = "Example of Using Apache Commons CLI";
   final String usageFooter = "See http://marxsoftware.blogspot.com/ for further details.";
   out.println("\n====");
   out.println("HELP");
   out.println("====");
   formatter.printHelp(syntax, usageHeader, options, usageFooter);
}

这篇文章演示了使用 Apache Commons CLI 实现一些与 Java 应用程序中的命令行解析相关的最常见功能,包括选项“定义”、命令行参数“解析”、已解析命令行参数的“询问”,以及与命令行参数相关的帮助/使用细节。以下是在选择框架或库以帮助在 Java 中进行命令行解析时要考虑的 Apache Commons CLI 的一些其他特性。

  • Apache Commons CLI 是开源的,并获得了 Apache License, Version 2.0 的许可。
  • 当前版本的 Apache Commons CLI (1.4) 需要 J2SE 5 或更高版本。
  • Apache Commons CLI 不需要任何第三方库单独下载或引用。
  • Apache Commons CLI 1.4 主 JAR (commons-cli-1.4.jar) 的大小约为 53 MB。
  • Apache Groovy 通过 CliBuilder 提供基于 Apache Commons CLI 的开箱即用的命令行解析功能。
  • Maven 存储库 显示 近 1800 个依赖项 Apache Commons CLI,包括 Apache Groovy
  • Apache Commons CLI 已经存在了一段时间; 最初的 1.0 版本是在 2002 年 11 月。

对我来说,在简单的 Java 应用程序中实现命令行界面时,Apache Commons CLI 的最大优势之一是我已经熟悉 Groovy 对 CliBuilder 的内置使用。因为与使用 Java 相比,我将 Groovy 更频繁地用于基于简单命令行的脚本和工具,因此对 Groovy 的基本 Apache Commons CLI 用法的熟悉在返回到 Java 时很有帮助。

其他参考资料

  • Apache Commons CLI
  • Apache Commons CLI 介绍
  • Apache Commons CLI 使用场景
  • Apache Commons CLI API 文档
  • 使用 Apache Commons CLI 进行命令行解析(我 2008 年关于 Apache Commons CLI 的帖子)
标签: Java教程
地址:https://www.cundage.com/article/jcg-java-command-line-interfaces-part-1-apache-commons-cli.html