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

位置:首页>文章>详情   分类: Java教程 > 编程技术   阅读(328)   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 的帖子)
标签2: Java教程
地址:https://www.cundage.com/article/jcg-java-command-line-interfaces-part-1-apache-commons-cli.html

相关阅读

Java HashSet 教程展示了如何使用 Java HashSet 集合。 Java哈希集 HashSet 是一个不包含重复元素的集合。此类为基本操作(添加、删除、包含和大小)提供恒定时间性...
SpringApplicationBuilder 教程展示了如何使用 SpringApplicationBuilder 创建一个简单的 Spring Boot 应用程序。 春天 是用于创建企业应...
通道是继 buffers 之后 java.nio 的第二个主要新增内容,我们在之前的教程中已经详细了解了这一点。通道提供与 I/O 服务的直接连接。 通道是一种在字节缓冲区和通道另一端的实体(通...
课程大纲 Elasticsearch 是一个基于 Lucene 的搜索引擎。它提供了一个分布式的、支持多租户的全文搜索引擎,带有 HTTP Web 界面和无模式的 JSON 文档。 Elasti...
解析器是强大的工具,使用 ANTLR 可以编写可用于多种不同语言的各种解析器。 在这个完整的教程中,我们将: 解释基础:什么是解析器,它可以用来做什么 查看如何设置 ANTLR 以便在 Java...
Java 是用于开发各种桌面应用程序、Web 应用程序和移动应用程序的最流行的编程语言之一。以下文章将帮助您快速熟悉 Java 语言,并迈向 API 和云开发等更复杂的概念。 1. Java语言...
Java中的继承是指子类继承或获取父类的所有非私有属性和行为的能力。继承是面向对象编程的四大支柱之一,用于提高层次结构中类之间的代码可重用性。 在本教程中,我们将了解 Java 支持的继承类型,...
Java Message Service 是一种支持正式通信的 API,称为 网络上计算机之间的消息传递。 JMS 为支持 Java 程序的标准消息协议和消息服务提供了一个通用接口。 JMS 提...
之前,我介绍了spring 3 + hibernate 集成 示例和struts 2 hello world 示例。在本教程中,我将讨论在将 spring 框架与 struts 与 hibern...
Java 项目中的一项常见任务是将日期格式化或解析为字符串,反之亦然。解析日期意味着你有一个代表日期的字符串,例如“2017-08-3”,你想把它转换成一个代表 Java 中日期的对象,例如Ja...