Reading a resource file from within jar

2018-12-31 00:23发布

I would like to read a resource from within my jar like so:

File file;
file = new File(getClass().getResource("/file.txt").toURI());
BufferredReader reader = new BufferedReader(new FileReader(file));

//Read the file

and it works fine when running it in Eclipse, but if I export it to a jar the run it there is an IllegalArgumentException:

Exception in thread "Thread-2"
java.lang.IllegalArgumentException: URI is not hierarchical

and I really don't know why but with some testing I found if I change

file = new File(getClass().getResource("/file.txt").toURI());

to

file = new File(getClass().getResource("/folder/file.txt").toURI());

then it works the opposite (it works in jar but not eclipse).

I'm using Eclipse and the folder with my file is in a class folder.

11条回答
浮光初槿花落
2楼-- · 2018-12-31 01:14

You can use class loader which will read from classpath as ROOT path (without "/" in the beginning)

InputStream in = getClass().getClassLoader().getResourceAsStream("file.txt"); 
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
查看更多
大哥的爱人
3楼-- · 2018-12-31 01:19

If you wanna read as a file, I believe there still is a similar solution:

    ClassLoader classLoader = getClass().getClassLoader();
    File file = new File(classLoader.getResource("file/test.xml").getFile());
查看更多
几人难应
4楼-- · 2018-12-31 01:22

Up until now (December 2017), this is the only solution I found which works both inside and outside the IDE.

Use PathMatchingResourcePatternResolver

Note: it works also in spring-boot

In this example I'm reading some files located in src/main/resources/my_folder:

try {
    // Get all the files under this inner resource folder: my_folder
    String scannedPackage = "my_folder/*";
    PathMatchingResourcePatternResolver scanner = new PathMatchingResourcePatternResolver();
    Resource[] resources = scanner.getResources(scannedPackage);

    if (resources == null || resources.length == 0)
        log.warn("Warning: could not find any resources in this scanned package: " + scannedPackage);
    else {
        for (Resource resource : resources) {
            log.info(resource.getFilename());
            // Read the file content (I used BufferedReader, but there are other solutions for that):
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(resource.getInputStream()));
            String line = null;
            while ((line = bufferedReader.readLine()) != null) {
                // ...
                // ...                      
            }
            bufferedReader.close();
        }
    }
} catch (Exception e) {
    throw new Exception("Failed to read the resources folder: " + e.getMessage(), e);
}
查看更多
何处买醉
5楼-- · 2018-12-31 01:24

Rather than trying to address the resource as a File just ask the ClassLoader to return an InputStream for the resource instead via getResourceAsStream:

InputStream in = getClass().getResourceAsStream("/file.txt"); 
BufferedReader reader = new BufferedReader(new InputStreamReader(in));

As long as the file.txt resource is available on the classpath then this approach will work the same way regardless of whether the file.txt resource is in a classes/ directory or inside a jar.

The URI is not hierarchical occurs because the URI for a resource within a jar file is going to look something like this: file:/example.jar!/file.txt. You cannot read the entries within a jar (a zip file) like it was a plain old File.

This is explained well by the answers to:

查看更多
骚的不知所云
6楼-- · 2018-12-31 01:27

I think this should be works in java as well. The following code I use is using kotlin.

val resource = Thread.currentThread().contextClassLoader.getResource('resources.txt')
查看更多
登录 后发表回答