【问题标题】:Listing resource files from a JAR列出 JAR 中的资源文件
【发布时间】:2016-12-28 05:02:24
【问题描述】:

我已经迁移了一个 Java 项目以使用 Gradle,它在 IntelliJ 或使用命令行时运行良好。

但是,当我使用 FatJar 将其打包成一个独立的 JAR 时,我在访问我的项目的资源时遇到了一些问题。

这是当前代码。它递归地列出queries 文件夹中的.sql 文件,并将每个文件放入一个地图中。

private static void loadQueriesFrom(final String baseDir) throws IOException {
    final InputStream is = Queries.class.getResourceAsStream(baseDir);

    if (is == null)
        return;
    
    List<String> queryFiles = IOUtils.readLines(is, Charsets.UTF_8);
    
    for (String queryFile: queryFiles) {
        final int index = queryFile.lastIndexOf(".sql");
        
        if (index == -1) {
            loadQueriesFrom(baseDir + queryFile + "/"); // directory
        }
        else {
            final String queryName = queryFile.substring(0, index).toLowerCase();

            queries.put(baseDir.substring(QUERY_DIRECTORY.length()) + queryName, IOUtils.toString(Queries.class
                    .getResourceAsStream(baseDir + queryFile)));

        }
    }
       
}

// First call is
loadQueriesFrom("/queries");

我的目录结构如下:

- src
  - main
      - java
      - resources
          - queries
  - test

这段代码可以正常工作,除非它被打包在 JAR 中:在这种情况下,is(第 1 行)始终为空。这是我的 fatjar 配置:

task fatjar(type: Jar) {
    baseName = project.name
    from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
    with jar
    manifest {
        attributes 'Implementation-Title': 'My project name', 'Implementation-Version': version
        attributes 'Main-Class': 'org.mypackage.MyMainClass'
    }
}

如果我打开 .jar 生成的文件,结构看起来像

- org
    - mypackage
        ...
- queries

所以 queries 文件夹 包含在 JAR 中,但由于某种原因 getResourceAsStream 无法列出它。但是,它可以访问单个文件。如果我插入以下行,我会得到预期的结果。

Queries.class.getResourceAsStream("/queries/collaborators/get_collab_list.sql")

我尝试过的:

  • /queries 更改为queries

  • getResourceAsStream(...) 更改为getClassLoader().getResourceAsStream(...)

  • 两者

    我见过this answer,但看起来有点矫枉过正。

帮助表示赞赏。谢谢!

【问题讨论】:

标签: java gradle jar spark-java


【解决方案1】:

将目录资源转换为文件。忽略异常,最基本的形式可能如下所示:

URL url = Queries.class.getResource("/queries");
File dir = new File(url.toURI());
for (File file : dir.listFiles()) {
    // do something with file
}

如果要递归文件树:

void doSomething(File file) {
    // do something with file
}

void processFile(File file) {
    if (file.isDirectory()) {
        for (File sub : file.listFiles()) {
            processFile(sub);
        }
    } else {
        doSomething(file);
    }
}

然后

URL url = Queries.class.getResource("/queries");
File dir = new File(url.toURI());
processFile(dir);

【讨论】:

  • 嘿,您的解决方案不起作用,文件构造函数抛出异常,指出 URI 无效(非分层)。我改变了查询的加载方式(延迟加载+缓存而不是预加载所有内容)。不过,我会给你赏金,以感谢你的回答,因为无论如何我都无法收回。 :-)
  • (不过我还不能提供赏金)
猜你喜欢
  • 2011-12-18
  • 1970-01-01
  • 1970-01-01
  • 2013-04-28
  • 2018-11-24
  • 2012-04-26
  • 2011-06-27
  • 2020-05-27
  • 1970-01-01
相关资源
最近更新 更多