`

JCommander(命令行参数解析工具)

阅读更多

Commander是一个用于解析命令行参数的Java框架,支持解析所有基本的数据类型,也支持将命令行解析成用户自定义的类型,只需要写一个转变函数。

1. JCommander用法

将用来表示参数的fields用@Parameter标识:

 

[java] view plain copy
 
  1. import com.beust.jcommander.Parameter;  
  2.    
  3. public class JCommanderExample {  
  4.   @Parameter  
  5.   private List<String> parameters = new ArrayList<String>();  
  6.    
  7.   @Parameter(names = { "-log""-verbose" }, description = "Level of verbosity")  
  8.   private Integer verbose = 1;  
  9.    
  10.   @Parameter(names = "-groups", description = "Comma-separated list of group names to be run")  
  11.   private String groups;  
  12.    
  13.   @Parameter(names = "-debug", description = "Debug mode")  
  14.   private boolean debug = false;  
  15. }  


JCommander就可以解析命令行中的参数了:

 

 

[java] view plain copy
 
  1. JCommanderExample jct = new JCommanderExample();  
  2. String[] argv = { "-log""2""-groups""unit" };  
  3. new JCommander(jct, argv);  
  4.    
  5. Assert.assertEquals(jct.verbose.intValue(), 2);  



 

2. 选项类型

Boolean:

 

[java] view plain copy
 
  1. @Parameter(names = "-debug", description = "Debug mode", arity = 1)  
  2. private boolean debug = true;  

boolean类型默认arity=0,这样的话不要用户为参数设置value,只要参数中有-debug就被parse成true,没有就parse成false。但是如果加上 arity=1,则需要用户明确指定value:

 

 

[java] view plain copy
 
  1. program -debug true  
  2. program -debug false  



String,Interger,Long:

 

对这几种类型,JCommander会尝试parse随后的参数,并上溯成参数的类型,如果参数不能成功上溯则会产生exception

 

[java] view plain copy
 
  1. @Parameter(names = "-log", description = "Level of verbosity")  
  2. private Integer verbose = 1;  
[java] view plain copy
 
  1. java Main -log 3  
  2. //got exception for the following one  
  3. java Main -log text  



Lists:

 

如果类型是List,则这个参数可出现多次

 

[java] view plain copy
 
  1. @Parameter(names = "-host", description = "The host")  
  2. private List<String> hosts = new ArrayList<String>();  

下例中fields hosts包含了两个字符串

 

 

[java] view plain copy
 
  1. java Main -host host1 -verbose -host host2  



Password:

 

指明password为true表明这个field是password,我们不想他出现在命令行上,遇到password的参数,用户会被要求在prompt中输入密码

 

[java] view plain copy
 
  1. public class ArgsPassword {  
  2.   @Parameter(names = "-password", description = "Connection password", password = true)  
  3.   private String password;  
  4. }  



Echo Input:

 

当你想让password显示在prompt中时,需要设置echoInput=true,这个setting只有在password=true时才有效

 

[java] view plain copy
 
  1. public class ArgsPassword {  
  2.   @Parameter(names = "-password", description = "Connection password", password = true, echoInput = true)  
  3.   private String password;  
  4. }  



 

 

3. 自定义类型

当需要更负责的参数时,比如files,host names,lists等,我们可以写一个转换器(converter)来将参数转换成我们想要的格式或类型。转换器需要实现IStringConverter接口

 

[java] view plain copy
 
  1. public interface IStringConverter<T> {  
  2.   T convert(String value);  
  3. }  

 

a. 通过annotation实现:

下面的converter将string转换成file

 

[java] view plain copy
 
  1. public class FileConverter implements IStringConverter<File> {  
  2.   @Override  
  3.   public File convert(String value) {  
  4.     return new File(value);  
  5.   }  
  6. }  


将参数对应的field定义成下面这样,注意要在annotation里指定converter

 

 

[java] view plain copy
 
  1. @Parameter(names = "-file", converter = FileConverter.class)  
  2. File file;  


b. 通过工厂 factory 实现:

 

在每个parameter annotation中都指定converter有点烦,可以通过factory解决这个问题。

比如你要将下面的参数解析成host和port java App -target example.com:8080
定义一个类来放参数

 

[java] view plain copy
 
  1. public class HostPort {  
  2.   private String host;  
  3.   private Integer port;  
  4. }  


写个converter把参数String转换成HostPort

 

 

[java] view plain copy
 
  1. class HostPortConverter implements IStringConverter<HostPort> {  
  2.   @Override  
  3.   public HostPort convert(String value) {  
  4.     HostPort result = new HostPort();  
  5.     String[] s = value.split(":");  
  6.     result.host = s[0];  
  7.     result.port = Integer.parseInt(s[1]);  
  8.    
  9.     return result;  
  10.   }  
  11. }  

写一个Factory,作用是返回converter

 

 

[java] view plain copy
 
  1. public class Factory implements IStringConverterFactory {  
  2.   public Class<? extends IStringConverter<?>> getConverter(Class forType) {  
  3.     if (forType.equals(HostPort.class)) return HostPortConverter.class;  
  4.     else return null;  
  5.   }  

参数类也很简单,参数类型直接用HostPort就好了

 

 

[java] view plain copy
 
  1. public class ArgsConverterFactory {  
  2.   @Parameter(names = "-hostport")  
  3.   private HostPort hostPort;  
  4. }  

没有看到Factory用在什么地方?是在你的程序创建JCommander时传进去的

 

 

[java] view plain copy
 
  1. ArgsConverterFactory a = new ArgsConverterFactory();  
  2. JCommander jc = new JCommander(a);  
  3. jc.addConverterFactory(new Factory());  
  4. jc.parse("-hostport""example.com:8080");  
  5.    
  6. Assert.assertEquals(a.hostPort.host, "example.com");  
  7. Assert.assertEquals(a.hostPort.port.intValue(), 8080);  




4. 参数验证
通过提供一个实现了IParameterValidator接口的类,可以让JCommander验证你的参数

 

 

[java] view plain copy
 
  1. public interface IParameterValidator {  
  2.  /** 
  3.    * Validate the parameter. 
  4.    * 
  5.    * @param name The name of the parameter (e.g. "-host"). 
  6.    * @param value The value of the parameter that we need to validate 
  7.    * 
  8.    * @throws ParameterException Thrown if the value of the parameter is invalid. 
  9.    */  
  10.   void validate(String name, String value) throws ParameterException;  
  11. }  

下面这个validator可以验证提供的参数为正整数

 

 

[java] view plain copy
 
  1. public class PositiveInteger implements IParameterValidator {  
  2.  public void validate(String name, String value)  
  3.       throws ParameterException {  
  4.     int n = Integer.parseInt(value);  
  5.     if (n < 0) {  
  6.       throw new ParameterException("Parameter " + name + " should be positive (found " + value +")");  
  7.     }  
  8.   }  
  9. }  

在parameter annotation中用validateWith来指定验证器

 

 

[java] view plain copy
 
  1. @Parameter(names = "-age", validateWith = PositiveInteger.class)  
  2. private Integer age;  

 

 

 

5. 主参数

我们可以定义一个main parameter来放所有参数,这个参数不用指定names,必须为List<String>类型

 

[java] view plain copy
 
  1. @Parameter(description = "Files")  
  2. private List<String> files = new ArrayList<String>();  
  3.    
  4. @Parameter(names = "-debug", description = "Debugging level")  
  5. private Integer debug = 1;  

run下面命令行,files会保存‘file1’和‘file2’

 

 

[java] view plain copy
 
  1. java Main -debug file1 file2  




6. 私有参数

 

参数可以是private的

 

[java] view plain copy
 
  1. public class ArgsPrivate {  
  2.   @Parameter(names = "-verbose")  
  3.   private Integer verbose = 1;  
  4.    
  5.   public Integer getVerbose() {  
  6.     return verbose;  
  7.   }  
  8. }  

 

 

[java] view plain copy
 
  1. ArgsPrivate args = new ArgsPrivate();  
  2. new JCommander(args, "-verbose""3");  
  3. Assert.assertEquals(args.getVerbose().intValue(), 3);  




7. 参数分隔符

参数默认用空格分隔,但是我们也可以指定自己的分隔符,比如用“:”, “=”等,java Main -log:3
可以在参数类定义中使用@Parameter annotation指定分隔符

 

[java] view plain copy
 
  1. @Parameters(separators = "=")  
  2. public class SeparatorEqual {  
  3.   @Parameter(names = "-level")  
  4.   private Integer level = 2;  
  5. }  



 

8. 多重描述(多个参数类)

你可以将参数放在不同的参数类中,比如定义以下两个含有不同参数的参数类

 

[java] view plain copy
 
  1. public class ArgsMaster {  
  2.   @Parameter(names = "-master")  
  3.   private String master;  
  4. }  
[java] view plain copy
 
  1. public class ArgsSlave {  
  2.   @Parameter(names = "-slave")  
  3.   private String slave;  
  4. }  

使用时将两个类都传入JCommander

 

 

[java] view plain copy
 
  1. ArgsMaster m = new ArgsMaster();  
  2. ArgsSlave s = new ArgsSlave();  
  3. String[] argv = { "-master""master""-slave""slave" };  
  4. new JCommander(new Object[] { m , s }, argv);  
  5.    
  6. Assert.assertEquals(m.master, "master");  
  7. Assert.assertEquals(s.slave, "slave");  



9. @语法

 

JCommander支持从文件中获取并解析参数,比如文件/tmp/params中包含了以下内容

 

[java] view plain copy
 
  1. -verbose  
  2. file1  
  3. file2  
  4. file3  

在命令行中用@指定文件路径即可

 

 

[java] view plain copy
 
  1. java Main @/tmp/parameters  




10. 参数value数量(Arities)

 

有时候你想为一个参数设置多个值,这时就要用到arity,比如-pairs需要两个values,则设置arity=2

 

[java] view plain copy
 
  1. @Parameter(names = "-pairs", arity = 2, description = "Pairs")  
  2. private List<String> pairs;  

JCommander就会为pairs接收两个values

 

 

[java] view plain copy
 
  1. java Main -pairs slave master  

注意想接收多个value的参数需要设置成List<String>类型,boolean类型默认arity为0,String、Integer、int、Long、long默认arity都为1。

 

 

可变参数值数量,设置variableArity=true,你可以指定一个参数接收不定数量的values

 

[java] view plain copy
 
  1. @Parameter(names = "-foo", variableArity = true)  
  2. public List<String> foo = new ArrayList<String>();  

下面两个例子一个接收2个参数,一个接收3个参数

 

 

[java] view plain copy
 
  1. program -foo a1 a2 a3 -bar  
  2. program -foo a1 -bar  




11. 多重选项名

同一个选项(option)可以有不同别名,比如--recursive,可以有一个缩写-r,可以通过给names设置多个值实现

 

[java] view plain copy
 
  1. @Parameter(names = { "-d""--outputDirectory" }, description = "Directory")  
  2. private String outputDirectory;  

下面两种都可以给outputDirectory赋值

 

 

[java] view plain copy
 
  1. </pre><pre name="code" class="java">java Main -d /tmp  
  2. java Main --outputDirectory /tmp  



12. 其他选项配置

 

JCommander#setCaseSensitiveOptions(boolean):选项是否大小写敏感,如果设置成true,则‘-option' 和'-OPTION'是不同的选项

JCommander#setAllowAbbreviatedOptions(boolean):打开选项缩写功能,’-op‘可以表示’-option‘选项,如果选项缩写太模糊不能定位到某个选项,则会throw一个ParameterException

 

 

13. 必须和可选选项

@Parameter annotation的required设置为true则表示此选项为必须的,否则为可选(默认为可选)

 

[java] view plain copy
 
  1. @Parameter(names = "-host", required = true)  
  2. private String host;  




 

14. 默认值

一般情况下直接给选项赋值就可以了

 

[java] view plain copy
 
  1. private Integer logLevel = 3;  

如果有更复杂的情况,比如对某些选项可以再不同的类里重复使用,或者你想把所有的default value都存在同一个地方比如一个XML文件,这些可以通过实现IDefaultProvider接口达成

 

 

[java] view plain copy
 
  1. public interface IDefaultProvider {  
  2.   /** 
  3.    * @param optionName The name of the option as specified in the names() attribute 
  4.    * of the @Parameter option (e.g. "-file"). 
  5.    * 
  6.    * @return the default value for this option. 
  7.    */  
  8.   String getDefaultValueFor(String optionName);  
  9. }  

实例

 

 

[java] view plain copy
 
  1. //这是个内部类  
[java] view plain copy
 
  1. private static final IDefaultProvider DEFAULT_PROVIDER = new IDefaultProvider() {  
  2.   @Override  
  3.   public String getDefaultValueFor(String optionName) {  
  4.     return "-debug".equals(optionName) ? "false" : "42";  
  5.   }  
  6. };  
  7.    
  8. // ...  
  9.    
  10. JCommander jc = new JCommander(new Args());  
  11. jc.setDefaultProvider(DEFAULT_PROVIDER); //把default provider传入  




15. 帮助选项

 

非常简单

 

[java] view plain copy
 
  1. @Parameter(names = "--help", help = true)  
  2. private boolean help;  



 

 

16. 更多复杂的命令语法

想git之类的工具,除了git命令本身需要选项,它还包含一些子命令,如git commit,子命令本身也包含一些选项

 

[java] view plain copy
 
  1. git commit --amend -m "Bug fix"  

上面的命令中,commit在JCommander中叫做’commands‘, 我们要为这个子命令单独创建一个类

 

 

[java] view plain copy
 
  1. @Parameters(separators = "=", commandDescription = "Record changes to the repository")  
  2. private class CommandCommit {  
  3.    
  4.   @Parameter(description = "The list of files to commit")  
  5.   private List<String> files;  
  6.    
  7.   @Parameter(names = "--amend", description = "Amend")  
  8.   private Boolean amend = false;  
  9.    
  10.   @Parameter(names = "--author")  
  11.   private String author;  
  12. }  


再为另一个git命令add创建一个类

 

 

[java] view plain copy
 
  1. @Parameters(commandDescription = "Add file contents to the index")  
  2. public class CommandAdd {  
  3.    
  4.   @Parameter(description = "File patterns to add to the index")  
  5.   private List<String> patterns;  
  6.    
  7.   @Parameter(names = "-i")  
  8.   private Boolean interactive = false;  
  9. }  


创建好后要在JCommander对象里通过addCommand注册这些命令,当然我们也可以创建一个主要的参数类来接受git的参数

 

 

[java] view plain copy
 
  1. CommandMain cm = new CommandMain();  
  2. JCommander jc = new JCommander(cm);  
  3.    
  4. CommandAdd add = new CommandAdd();  
  5. jc.addCommand("add", add);  
  6. CommandCommit commit = new CommandCommit();  
  7. jc.addCommand("commit", commit);  
  8.    
  9. jc.parse("-v""commit""--amend""--author=cbeust""A.java""B.java");  
  10.    
  11. Assert.assertTrue(cm.verbose);  
  12. Assert.assertEquals(jc.getParsedCommand(), "commit");  
  13. Assert.assertTrue(commit.amend);  
  14. Assert.assertEquals(commit.author, "cbeust");  
  15. Assert.assertEquals(commit.files, Arrays.asList("A.java""B.java"));  




 

17. Exception

JCommander发现错误时会抛出ParameterExcpetion,这是一个runtime exception

 

 

18. usage

可以再JCommander实例中调用usage()方法获取命令行使用方法

 

 

19. 隐藏参数

如果不想某些选项出现在usage里,可以隐藏他们

 

[java] view plain copy
 
  1. @Parameter(names = "-debug", description = "Debug mode", hidden = true)  
  2. private boolean debug = false;  



 

20. 国际化

选项的描述(description)可以国际化,首先在类上使用@Parameter指定消息bundle的名字,然后在选项的@Parameter中使用descriptionKey指定bundle中的key

 

[java] view plain copy
 
  1. @Parameters(resourceBundle = "MessageBundle")  
  2. private class ArgsI18N2 {  
  3.   @Parameter(names = "-host", description = "Host", descriptionKey = "host")  
  4.   String hostName;  
  5. }  

在MessageBundle中,定义host如下

 

 

[java] view plain copy
 
  1. host:主机  



21. 参数代理

 

使用@ParameterDelegate可以在主参数类中引用其他的代理参数类

 

[java] view plain copy
 
  1. class Delegate {  
  2.   @Parameter(names = "-port")  
  3.   private int port;  
  4. }  
  5.    
  6. class MainParams {  
  7.   @Parameter(names = "-v")  
  8.   private boolean verbose;  
  9.    
  10.   @ParametersDelegate  
  11.   private Delegate delegate = new Delegate();  
  12. }  

使用时只需在JCommander中指定主参数类

 

 

[java] view plain copy
 
  1. MainParams p = new MainParams();  
  2. new JCommander(p).parse("-v""-port""1234");  
  3. Assert.assertTrue(p.isVerbose);  
  4. Assert.assertEquals(p.delegate.port, 1234);  



22. 动态参数

 

JCommander允许接收没有预先定义的选项,比如’-Da=b -Dc=d‘, Da和Dc没有在参数类中定义,这些参数要用@DynamicParameter annotation标记的类型为Map<String, String>的选项接收,动态参数可以重复多次

 

[java] view plain copy
 
  1. @DynamicParameter(names = "-D", description = "Dynamic parameters go here")  
  2. private Map<String, String> params = new HashMap<String, String>();  

通过使用assignment属性,可以用其他符号代替’=‘作为赋值符号

 

 

 

 

 

 

 

http://blog.csdn.net/navyhu/article/details/40430267

分享到:
评论

相关推荐

    Java命令行选项解析之Commons-CLI & Args4J & JCommander

    JCommander 是由Cédric Beust开发的一个更高级的命令行参数解析库,尤其适用于具有多个命令或子命令的复杂应用。JCommander允许你定义多个命令模型类,每个类对应一个命令,每个命令有自己的参数。它还支持命令行...

    MainArgsHandler:Java的命令行参数处理器

    1. **参数解析**:识别参数类型,如单值参数、开关参数(如`-v`或`--verbose`)和复合参数(如`--file path/to/file`)。 2. **参数验证**:检查参数的有效性,例如确保必需的参数已提供,或者参数值符合预期格式。...

    jflag:简单的命令行选项解析库

    在Java中,通常我们会使用如Apache Commons CLI、JCommander或jopt-simple等库来解析命令行参数。jflag作为一个轻量级的替代品,可能旨在提供更简洁的代码实现,减少依赖,并可能专注于基本功能,使开发者能够快速...

    完整jar包资源,COULD NOT FIND jcommander,包缺失使用

    `jcommander`是一个Java库,用于命令行参数解析,它简化了从命令行参数中提取和验证数据的过程。 描述中提到的“打包找不到 jcommander COULD NOT FIND jcommander-1.48”表明在构建过程中,Maven或Gradle无法从...

    使用Java编写基于命令行的程序

    - 对于复杂的命令行参数,可以使用第三方库,如Apache Commons CLI或JCommander。这些库可以帮助解析和验证命令行参数,提供更友好的用户界面。 - 如果只是简单的参数处理,可以手动解析`args`数组,例如检查参数...

    反编译class文件必备

    总之,"反编译class文件必备"是一个关于Java开发中的高级技巧,它涉及到对字节码的理解、使用反编译工具以及可能的命令行参数解析,这些都是成为出色Java开发者和架构师道路上不可或缺的技能。通过学习和实践这些...

    properties-generator-源码.rar

    4. **命令行参数解析**:项目可能使用了如Apache Commons CLI或JCommander等第三方库来处理命令行参数,允许用户自定义生成配置文件的选项。 5. **异常处理**:在处理I/O操作时,异常处理是必不可少的。源码中应...

    zxing jcommande java版

    JCommander可以解析命令行参数,确定用户想要执行的操作(如生成或扫描条形码),而ZXing则负责实际的条形码处理工作。 在实际项目中,首先你需要将`zxing.3.3.1.jar`和`jcommander.1.48.jar`添加到你的项目类路径...

    zxing_jar.zip

    3. **jcommander-1.72.jar**:这是一个命令行参数解析库,与ZXing库一起使用时,可以帮助开发者更方便地处理命令行输入。例如,如果你打算创建一个命令行工具来读取或生成条码,jcommander可以帮助解析命令行参数,...

    clipp:CLI参数解析器库

    `clipp`是一个基于Scala的命令行接口(CLI)参数解析器库,它为开发者提供了便利的方式来处理命令行输入,并生成详细的用法信息。在开发命令行工具时,正确解析和管理用户输入的参数是至关重要的,`clipp`正是为此...

    gherkin-2.6.0.zip

    这个解析器使得在Java程序中处理命令行参数和选项变得更加简单和直观。它可能包含了源代码、示例、文档以及相关的构建文件,帮助开发者轻松地实现对命令行输入的解析和验证,从而提高程序的可交互性和用户友好性。 ...

    TestNG环境搭建步骤和所需要的包.zip

    除了TestNG本身,你还需要JCommander库,这是一个用于命令行参数解析的工具,常常在TestNG测试中用于处理命令行输入。JCommander的下载地址同样需要访问官方网站或者通过Maven/Gradle等构建工具获取对应的依赖。在你...

    jar_files_hamcrestcore_Will_

    3. **jcommander-1.48.jar** - JCommander是一个解析命令行参数的库,常用于工具或命令行应用,帮助处理复杂的命令行选项和参数。 4. **commons-logging-1.1.3.jar** - Apache Commons Logging是一个日志抽象层,...

    JavaEye新闻月刊

    JCommander 1.0的发布,作为一个命令行参数解析库,简化了Java应用程序的命令行接口开发。 这一期的JavaEye月刊涵盖了从IDE到框架,再到数据库和开发工具的广泛内容,反映了当时Java生态系统的重要动态,对于学习和...

    java ping程序

    此外,为了实现类似命令行工具的功能,例如指定IP段或设置超时,可以使用命令行参数解析库,如Apache Commons CLI或JCommander。这样,用户可以通过提供不同的参数来定制ping行为。 总结来说,Java Ping程序是一个...

    zxing-3.3.0

    4. `jcommander-1.48.jar`:JCommander 是一个帮助处理命令行参数的Java库,ZXing可能使用它来解析用户输入,方便在命令行界面中使用ZXing的功能。 5. `javase-3.3.0.jar`:这个文件是ZXing的Java Standard Edition...

    perun-java-cli:用Java实现的Perun命令行客户端

    对于Perun-java-cli来说,可能使用了Java的IO流进行文件操作,使用了Apache Commons CLI或者JCommander等库来处理命令行参数,还可能使用了HTTP客户端库如OkHttp或Apache HttpClient来与Perun服务端进行通信。...

    CmdShop

    - 命令行参数解析是CmdShop的核心功能,可能使用了如JCommander或Apache Commons CLI等第三方库来处理命令行参数。 3. **项目构建与管理**: - CmdShop很可能使用Maven或Gradle作为构建工具,这两个工具可以管理...

    ScreenCaptrueProcess5

    参数解析是指从输入的字符串或者命令行中提取出有意义的数据,这些数据可以是数值、开关、选项等。在“ScreenCaptureProcess5”中,参数解析可能用于定制截图的特定行为,比如设置输出格式、尺寸、延迟时间等。参数...

    java学生成绩管理系统

    9. **命令行解析**:系统可能使用如JCommander这样的库来解析命令行参数,使得用户输入的命令能被正确识别和执行。 10. **用户交互设计**:尽管是命令行应用,但依然需要考虑用户体验,如提供友好的提示信息,错误...

Global site tag (gtag.js) - Google Analytics