Статьи

Интерфейсы командной строки Java (часть 29): сделай сам

В этой серии статей об анализе аргументов командной строки из Java кратко представлены 28 библиотек с открытым исходным кодом, которые можно использовать для обработки аргументов командной строки из кода Java. Даже с учетом этих 28 библиотек серия не охватывает все доступные библиотеки с открытым исходным кодом для анализа параметров командной строки из Java. Например, эта серия не охватывала docopt , getopt дельфина , DPML CLI , «другие» JArgP , java-getopt , ritopt , команду TE-CODE и, вероятно, многие другие библиотеки, о которых я не знаю. В этом посте рассматриваются соображения, которые можно сделать, пытаясь решить, следует ли накатывать свой собственный код синтаксического анализа аргументов командной строки в Java по сравнению с использованием одной из множества библиотек синтаксического анализа командной строки, которая уже доступна.

На первый взгляд, было бы легко сказать, что кто-то, кто разрабатывает свой собственный код синтаксического анализа командной строки на Java, может страдать от синдрома «Не изобретено здесь» . Тем не менее, я все еще иногда пишу свой собственный простой код обработки командной строки и обрисую ситуации, в которых я это делаю.

Многие из библиотек, описанных в этой серии , невелики. Однако в тех случаях, когда синтаксический анализ командной строки очень прост, даже эти меньшие библиотеки могут быть тяжелее, чем то, что необходимо для выполняемой работы. Примеры, которые я показываю в этом посте, являются типом, который может соответствовать этой категории. Вероятность того, что разработчик разработает собственный код обработки командной строки, вероятно, возрастает по мере того, как возрастает сложность требуемого анализа командной строки и уменьшается трудность введения новых библиотек в среду развертывания. Процесс также может влиять на решение, так как некоторые разработчики могут решить реализовать собственный код обработки командной строки, а не ждать необходимых разрешений для использования идентифицированной библиотеки.

Самая простая ситуация, в которой не нужно использовать библиотеку синтаксического анализа командной строки для Java, — это, очевидно, те ситуации, в которых аргументы командной строки не нужны. На самом деле, вполне вероятно, что гораздо больше разработчиков Java никогда или редко используют параметры командной строки, поскольку многие используют веб-серверы, серверы приложений или другие контейнеры (такие как Spring) для запуска, что они не думают о командной строке Разбор для их применения. Даже некоторые простые приложения на основе командной строки могут принимать значения или считывать значения из предполагаемого местоположения и не нуждаются в аргументах, передаваемых им.

Если у меня будет только один аргумент для чтения из командной строки, я сам напишу этот простой код. Учебные руководства по Java содержат раздел об аргументах командной строки, в котором представлена ​​базовая обработка аргументов командной строки в Java. От нуля до многих строк в командной строке, следующих за именем исполняемого приложения Java, предоставляются приложению Java через аргументы String[] или String... для классической функции public static void main . Простой листинг кода ниже показывает, как можно обрабатывать один ожидаемый аргумент командной строки.

Разбор единственного необходимого аргумента

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
/**
 * Demonstrate processing a single provided argument.
 *
 * @param arguments Command-line arguments; expecting a
 *    String-based name.
 */
public static void main(final String[] arguments)
{
   if (arguments.length < 1)
   {
      out.println("\nNo name provided; please provide a name.\n");
      out.println("\tUSAGE: SingleArgMain <name>");
   }
   else
   {
      out.println("Hello " + arguments[0] + "!");
   }
}

Приведенный выше код было легко написать, потому что был один параметр командной строки, у него не было аргумента, который нужно было добавить, и это было необходимо. Учитывая все эти допущения, написать код синтаксического анализа командной строки относительно просто.

Если приложению требуется два аргумента, все равно довольно просто обработать это непосредственно в Java без сторонней библиотеки. Это продемонстрировано в следующем листинге кода, который имитирует приложение, которое принимает имя / путь файла XML для проверки и имя / путь XSD, для которого этот XML должен проверяться.

Разбор двух обязательных аргументов

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
/**
 * Demonstrate processing two required provided arguments.
 *
 * @param arguments Command-line arguments; expecting a String-based
 *    path and file name of an XML file to be validated and a
 *    String-based path and file name of the XSD file against which
 *    the XML file will be validated.
 */
public static void main(final String...arguments)
{
   if (arguments.length < 2)
   {
      out.println("\nXML file path/name and XSD file path/name not provided.\n");
      out.println("\tUSAGE: TwoArgsMain <xmlFilePathAndName> <xsdFilePathAndName>");
   }
   else
   {
      out.println("The provided XML file is '" + arguments[0]
         + "' and the provided XSD file is '" + arguments[1] + "'.");
   }
}

В публикациях этой серии я использовал примеры, в которых ожидалась обязательная опция, указывающая путь / имя файла, и необязательная опция, выражающая включенную многословность. Во всех этих примерах опция путь / имя файла представляла собой имя флага ( -f и / или --file ), за которым следовали «аргумент» или «значение» для этой опции. В этих примерах опция многословия не имела аргумента или значения, связанных с ним, а наличие -v или --verbose подразумевало включенную многословность. Это особенно легко сделать в Java без библиотеки, если я хочу немного изменить подход и предположить, что первым параметром командной строки является путь / имя файла, и предположить, что флаг многословия, если он указан, появляется после путь к файлу / имя. Другое предположение, облегчающее это, — это предположить, что, поскольку путь / имя файла является первым, мне не нужно фактически использовать флаг, такой как -file или -f . Со всеми этими допущениями пример кода показан ниже.

Пример серии: синтаксический анализ одного обязательного параметра и одного дополнительного параметра

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/**
 * Demonstrate parsing of command-line options for required file
 * path/name and for optional verbosity.
 *
 * @param arguments Expected command-line arguments; first String
 *    should be file path/name and, if applicable, second String
 *    should be the verbosity flag (-v or --verbose).
 */
public static void main(final String[] arguments)
{
   if (arguments.length < 1)
   {
      out.println("\nNo file path/name provided; please provide a file path/name.\n");
      out.println("\tUSAGE: SeriesExample <filePathAndName> [-v|--verbose]");
   }
   else
   {
      final String file = arguments[0];
      final String verboseString = arguments.length > 1 ? arguments[1] : "";
      final boolean verbose = verboseString.equals("-v") || verboseString.equals("--verbose");
      out.println("File path/name is '" + file + "' and verbosity is " + verbose);
   }
}

До сих пор у меня были относительно простые параметры синтаксического анализа командной строки из-за этих характеристик этих примеров:

  • Порядок аргументов командной строки был принят и неизменен.
  • Никогда не было более одного необязательного аргумента командной строки, и необязательный аргумент ожидался последним.
  • Никогда не требовался аргумент командной строки, состоящий из флага и значения, связанного с этим флагом.
  • Ни одна опция не зависела ни от какой другой опции.

Только что упомянутые характеристики позволяют упростить синтаксический анализ параметров командной строки из Java, поскольку число перестановок и комбинаций, к которым необходимо подготовиться, было значительно сокращено за счет требования упорядочения параметров, не допуская флагов со связанными значениями, которые должны обрабатываться вместе. (каждая строка в предоставленном String[] не зависит от всех других строк в этом массиве), и разрешает не более одного необязательного аргумента (и требует, чтобы он был последним).

По мере усложнения ситуации с аргументами командной строки мое желание использовать стороннюю библиотеку возрастает. Если я хочу иметь несколько необязательных аргументов или хочу иметь опции, которые состоят из флагов со связанными значениями, я с большей вероятностью перейду к сторонним библиотекам для анализа аргументов командной строки в Java. Использование большинства сторонних библиотек, описанных в этой серии, избавляет меня от необходимости беспокоиться об упорядочении опций и связях имен / флагов опций.

Одной из ситуаций, в которой может быть желательным накатывать собственный код синтаксического анализа командной строки в Java, является ситуация, когда эти потребности синтаксического анализа очень специфичны для конкретной ситуации, которая плохо обрабатывается существующими библиотеками, или когда ни одна из существующих библиотек адекватно не соответствует своей. необходимо. Однако при наличии более 30 библиотек, я сомневаюсь, что это будет происходить очень часто для большинства людей.

При разработке собственного кода синтаксического анализа командной строки в Java, помимо написания с нуля, есть и другие варианты, включая разветвление и расширение одной из библиотек с открытым исходным кодом или построение кода на платформе, подобной представленной в статье « Разбор аргументов командной строки в Java». : Использование эффективной среды Java для написания инструментов командной строки »(страницы 20 и 22 этого журнала Java Developer ).

Для небольших инструментов на основе Java простых подходов синтаксического анализа командной строки, показанных в этом посте, часто бывает достаточно, особенно если я единственный, кто может использовать этот инструмент. Однако, поскольку потенциальная пользовательская база увеличивается для Java-приложения, требования, изложенные в этом посте, могут стать обременительными, и использование сторонних библиотек, описанных в этой серии постов, может помочь в создании более удобного для пользователя аргумента командной строки. опыт. Для простейших инструментов и приложений на основе Java мне, возможно, удастся обойтись без собственного собственного кода синтаксического анализа командной строки. Однако для большинства значимых Java-приложений сторонняя библиотека имеет больше смысла, поскольку она предлагает значительно большую гибкость и простоту использования для конечных пользователей.

Дополнительные ссылки

Опубликовано на Java Code Geeks с разрешения Дастина Маркса, партнера нашей программы JCG . См. Оригинальную статью здесь: Интерфейсы командной строки Java (часть 29): Сделай сам

Мнения, высказанные участниками Java Code Geeks, являются их собственными.