Classloader和FileInputStream无法在JAR

时间:2016-10-13 09:32:19

标签: java jar

我用maven构建我的jar文件,它们包含所有依赖项,所以我可以通过

运行jar

java -jar

在jar中我有一个config.json,这是app-configuration。 我验证了config.json真的在jar中:

/> jar tf cloudimport-0.1-jar-with-dependencies.jar | grep config.json
config.json

但是当我运行应用程序时,它无法找到config.json:

ClassLoader classLoader = getClass().getClassLoader();
System.out.println(classLoader.getResource("config.json"));
File configFile =  new File(classLoader.getResource(fileName).getFile());
(Exception thrown here ->) FileReader fileReader = new FileReader(configFile);
BufferedReader br = new BufferedReader(fileReader);

产生

java -jar cloudimport-0.1-jar-with-dependencies.jar
jar:file:/home/ubuntu/cloudimport-0.1-jar-with-dependencies.jar!/config.json
java.io.FileNotFoundException: file:/home/ubuntu/cloudimport-0.1-jar-with-dependencies.jar!/config.json (No such file or directory)

运行上述代码的Class位于jar中:

com.test.cloudsync.config.AppConfig.class

如果我从windows中的intelliJ运行应用程序,它可以正常工作,但是从intelliJ执行意味着主类不是执行jar。

我已经搜索了这个,但答案如下: What is the difference between Class.getResource() and ClassLoader.getResource()?

没有帮助...

jar-contents

//编辑 建议是,Excpetion并没有被ClassLoader抛出 - 这是真的。我删除了一些东西,所以我可以限制范围,现在似乎问题是我尝试打开一个FileINputStream但这是不可能的,我想如果文件是一个罐子?

完整堆栈跟踪:

/> java -jar java_cloudsync/com/tsg/cloudimport/cloudimport/0.1/cloudimport-0.1-jar-with-dependencies.jar   
jar:file:/home/ubuntu/java_cloudsync/com/tsg/cloudimport/cloudimport/0.1/cloudimport-0.1-jar-with-dependencies.jar!/config.json
    java.io.FileNotFoundException: file:/home/ubuntu/java_cloudsync/com/tsg/cloudimport/cloudimport/0.1/cloudimport-0.1-jar-with-dependencies.jar!/config.json (No such file or directory)
            at java.io.FileInputStream.open0(Native Method)
            at java.io.FileInputStream.open(FileInputStream.java:195)
            at java.io.FileInputStream.<init>(FileInputStream.java:138)
            at java.io.FileReader.<init>(FileReader.java:72)
            at com.tsg.cloudsync.config.AppConfig.readConfigFile(AppConfig.java:33)
            at com.tsg.cloudsync.config.AppConfig.<init>(AppConfig.java:23)
            at com.tsg.cloudsync.awsutils.SQSSocket.<init>(SQSSocket.java:34)
            at com.tsg.cloudsync.awsutils.SQSSocket.<clinit>(SQSSocket.java:19)
            at com.tsg.cloudsync.NewFileWatchDog.main(NewFileWatchDog.java:24)
    Exception in thread "main" java.lang.ExceptionInInitializerError
            at com.tsg.cloudsync.NewFileWatchDog.main(NewFileWatchDog.java:24)
    Caused by: java.lang.NullPointerException
            at com.tsg.cloudsync.config.AppConfig.getAWSCredentials(AppConfig.java:50)
            at com.tsg.cloudsync.awsutils.SQSSocket.<init>(SQSSocket.java:35)
            at com.tsg.cloudsync.awsutils.SQSSocket.<clinit>(SQSSocket.java:19)
            ... 1 more

2 个答案:

答案 0 :(得分:1)

事实证明我正在尝试定义

ClassLoader classLoader = getClass().getClassLoader();
File f = new File(classLoader.getResource(fileName).getFile())
FileReader fileReader = new FileReader(configFile);
BufferedReader br = new BufferedReader(fileReader);

这是不可能的,因为jar本身就是一个文件。 因此,要获取文件的内容,请执行以下操作:

ClassLoader classLoader = getClass().getClassLoader();
InputStream in = classLoader.getResourceAsStream(fileName);
BufferedReader br = new BufferedReader(new InputStreamReader(in));

另请参阅此处: Reading a resource file from within jar

注意差异getResourceAsStream(fileName)getResource(fileName).getFile()

感谢您指出我正确的方向!

答案 1 :(得分:0)

假设遵循以下简单结构

bin/
src/AppConfig.java
src/config.json
src/manifest.mf

<强> AppConfig.java

package com.test.cloudsync;
public class AppConfig {
    void check() {
        ClassLoader classLoader = getClass().getClassLoader();
        System.out.println(classLoader.getResource("config.json"));
    }
    public static void main(String[] args) {
        new AppConfig().check();
    }
}

<强> MANIFEST.MF

Main-Class: com.test.cloudsync.AppConfig

编译并构建Jar文件

javac -d bin/ src/*.java
cp src/config.json bin/config.json
jar cfm test.jar src/manifest.mf -C bin/ .

运行Jar

java -jar test.jar

输出

jar:file:/tmp/foobar/test.jar!/config.json

这表明行ClassLoader classLoader = getClass().getClassLoader()

不会引发异常