简体   繁体   中英

Listing resource files from a JAR

I have migrated a Java project to use Gradle, and it works just fine in IntelliJ or using the command line.

However when I package it into a standalone JAR using FatJar, I have some issues accessing the ressources of my project.

Here is the current code. It recursively lists the .sql files from the queries folder, and for each file it puts it in a Map.

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");

My directory structure is as follows:

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

This piece of code works fine except when it is packaged in a JAR: in this case, is (line 1) is always null. Here's my fatjar configuration:

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'
    }
}

If I open the .jar generated file, the structure looks like

- org
    - mypackage
        ...
- queries

So the queries folder is included in the JAR but for some reason getResourceAsStream can't list it. However, it can access individual files. If I insert the following line, I get the intended result.

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

What I've tried:

  • changing /queries to queries

  • changing getResourceAsStream(...) by getClassLoader().getResourceAsStream(...)

  • both

    I've seen this answer , but it looks a bit overkill.

Help appreciated. Thanks!

Turn the directory resource into a File. Ignoring exceptions, in its most basic form could look something like this:

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

If you want to recurse the file tree:

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);
    }
}

then

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM