2016-09-01 141 views
0

我需要从位于每个jar根级别的属性文件“version.properties”中读取属性“product.build.number”。我天真的做法是:从jar中的属性文件读取特定属性

private static int getProductBuildNumber(File artefactFile) throws FileNotFoundException, IOException 
    { 
    try (ZipInputStream zip = new ZipInputStream(new FileInputStream(
     artefactFile))) 
    { 

     Set<String> possClasses = new HashSet<>(); 

     for (ZipEntry entry = zip.getNextEntry(); entry != null; entry = zip 
      .getNextEntry()) 
     { 
     if (!entry.isDirectory() && entry.getName().toLowerCase().equals(
      "version.properties")) 
     { 
      List<String> lines = IOUtils.readLines(zip, (String) null); 

      for (String line : lines) 
      { 
      if (line.startsWith("product.build.number")) 
      { 
       String[] split = line.split("="); 
       if (split.length == 2) 
       { 
       return Integer.parseInt(split[1]); 
       } 

      } 
      } 

     } 
     } 
    } 

    throw new IOException("product.build.number not found."); 

    } 

我想有更优雅和可靠的方法。有任何想法吗?

+0

你的做法看起来是正确的,如果你是从罐子读取属性文件的类路径之外 – vsminkov

回答

3

尝试像(未经测试):

private static int getProductBuildNumber(Path artefactFilePath) throws IOException{ 
    try(FileSystem zipFileSystem = FileSystems.newFileSystem(artefactFilePath, null)){ 
     Path versionPropertiesPath = zipFileSystem.getPath("/version.properties"); 
     Properties versionProperties = new Properties(); 
     try (InputStream is = Files.newInputStream(versionPropertiesPath)){ 
      versionProperties.load(is); 
     } 
     return Integer.parseInt(versionProperties.getProperty("product.build.number")); 
    } 
} 
+0

我必须注意它不会在内存中解包。它需要可写目录。 – vsminkov

+0

@vsminkov我不确定你的意思。 JRE附带的zip文件系统提供程序允许使用NIO.2 File API访问zip文件。请参阅:http://docs.oracle.com/javase/7/docs/technotes/guides/io/fsp/zipfilesystemprovider.html – Puce

+0

我的意思是这个解决方案需要额外的磁盘空间来执行解包(这里是一个[示例](http ://stackoverflow.com/questions/24863465/java-zip-file-system-provider-readonly-on-remote-drive-windows))。而'ZipInputStream'在内存中解包。 – vsminkov

0

你还没有说.jar文件是否在你的类路径中。

如果他们在你的classpath中,你应该使用Class.getResourceAsStream阅读条目:

try (InputStream propStream = getClass().getResourceAsStream("/version.properties")) { 
    // ... 
} 

如果他们.jar文件不在你的classpath,你应该创建一个jar:URL从文件。 JarURLConnection documentation中描述了这种URL的格式。

注意java.io.File的是过时的,你应该总是使用Path代替:

private static int getProductBuildNumber(Path artefactFile) 
throws IOException { 
    URL propsURL = new URL("jar:" + artefactFile.toUri() + "!/version.properties"); 
    try (InputStream propStream = propsURL.openStream()) { 
     // ... 
    } 
} 

不管数据的位置,你应该总是使用Properties类读取性能。 (解析属性文件自己意味着你必须考虑到的意见,Unicode转义字符,续行,以及所有可能的名称/值分隔符。)

Properties props = new Properties(); 
try (InputStream propStream = getClass().getResourceAsStream("/version.properties")) { 
    props.load(propStream); 
} 

int buildNumber = Integer.parseInt(
    props.getProperty("product.build.number")); 
+0

getClass()。getResourceAsStream在这里不起作用,我认为(多个罐子有一个version.properties文件在相同的位置 - 默认的类加载器只能看到第一个) – Puce