InputStream.getResourceAsStream()给出空指针异常

时间:2014-10-13 19:24:51

标签: java inputstream

persistenceProperties.load(is);在以下方法中抛出nullpointerexception如何解决此错误?

public void setUpPersistence(){

    final Properties persistenceProperties = new Properties();
    InputStream is = null;
    try {
        is = getClass().getClassLoader().getResourceAsStream("src/test/samples/persistence.properties");
        persistenceProperties.load(is);
    }catch (IOException ignored) {}
    finally {
        if (is != null) {try {is.close();} catch (IOException ignored) {}}
    }

    entityManagerFactory = Persistence.createEntityManagerFactory(
        "persistence.xml", persistenceProperties);
    }  

我试图通过将包含该方法的类移动到应用程序结构中的各个其他位置,并通过以下方式更改错误之前的代码行来尝试此操作:

is = getClass().getClassLoader().getResourceAsStream("persistence.properties");
is = getClass().getClassLoader().getResourceAsStream("/persistence.properties");
is = getClass().getClassLoader().getResourceAsStream("/src/test/samples/persistence.properties");
is = getClass().getClassLoader().getResourceAsStream("other/paths/after/moving/persistence.properties");

但每次调用该方法时仍会抛出错误。

这是eclipse项目目录结构的打印屏幕。包含该方法的类称为TestFunctions.java,并显示persistence.properties的位置:


**编辑:**

根据以下反馈,我将方法更改为:

public void setUpPersistence(){
    final Properties persistenceProperties = new Properties();
    InputStream is = null;
    try {
        is = getClass().getClassLoader().getResourceAsStream("persistence.properties");
        persistenceProperties.load(is);
    }catch (IOException i) {i.printStackTrace();}
    finally {
        if (is != null) {try {is.close();} catch (IOException ignored) {}}
    }
    entityManagerFactory = Persistence.createEntityManagerFactory(
        "persistence.xml", persistenceProperties);
}  

我还将mainTest.TestFunctions.java移动到src/test/java。这些都会导致以下新的堆栈跟踪:

Exception in thread "main" java.lang.NoClassDefFoundError: maintest/TestFunctions
    at maintest.Main.main(Main.java:7)
Caused by: java.lang.ClassNotFoundException: maintest.TestFunctions
    at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
    ... 1 more  

7 个答案:

答案 0 :(得分:5)

两件事:

首先,尝试test/samples/.../test/samples/...

的路径

其次,更重要的是,永远不要写这个:

try {
    // some stuff
} catch (IOException ignored) {}

所有这一切都说:做一些事情,如果出错了,那么无声地失败这绝对不是正确的事情:如果有'一个问题,你想知道它,而不是疯狂地冲上去,好像什么也没发生过一样。要么在catch块中进行一些明智的处理,要么不要使用try / catch并在方法签名中添加throws IOException以便它可以传播向上。

但此刻,你只是在地毯下扫地。

答案 1 :(得分:4)

简短回答: 将persistence.properties移动到src / main / resources,在src / main / java中同时使用Main.java和TestFunctions.java,然后使用

 getClass().getClassLoader().getResourceAsStream("persistence.properties");

加载属性文件。

给出解释的答案很长:

正如其他人所暗示的那样 - 在Maven项目结构中,您(通常)有两个目录树:/src/main/src/test。一般意图是任何“真实”代码,资源等应该放在/src/main中,而仅测试的项目应该放在/src/test中。编译和运行时,test树中的项目通常可以访问main树中的项目,因为它们旨在测试main中的内容;但是,main树中的项目通常无权访问test树中的项目,因为根据测试内容生成“生产”代码通常是个坏主意。因此,由于Main.java依赖于TestFunctions.java,而TestFunctions.java依赖于persistence.properties,如果Main位于src/main中,那么TestFunctions和persistence.properties也必须同样如此。

答案 2 :(得分:1)

ClassLoader.getResourceAsStream()加载资源,就像加载类一样。因此它从运行时类路径加载它们。不是来自项目中的源目录。

您的班级Main位于maintest包中,因此其名称为maintest.Main。我知道甚至没有看到代码,因为Main.java位于名为maintest的目录下,该目录位于源目录的正下方。

persistence.properties文件直接位于源目录(src/test/resources)下。在运行时,它是默认包中类路径的根。它的名称是persistence.properties,而不是src/test/samples/peristence.properties。所以代码应该是

 getClass().getClassLoader().getResourceAsStream("persistence.properties");

从samples目录中无法加载任何内容,因为此目录不在任何源目录下,因此不会被Eclipse编译,因此不能用于ClassLoader。

答案 3 :(得分:1)

您的IDE使用两个不同的范围:

  • 生产范围:src / main / java + src / main / resources文件夹和
  • 测试范围:src / test / java + src / test / resources

似乎您正在尝试从生产范围执行程序,而persistence.properties文件则放在测试范围内。

如何解决:

  • 将测试放入src / test / java或
  • 将persistence.properties移动到src / main / resources

答案 4 :(得分:1)

我会尽量让这个问题更简单!

这里你的主类在你提到的 src/main/java 中,所以你应该创建另一个源来存储你的属性文件,说 src/main/resources 你已经完成了,然后将你的属性文件存储在这个源中,所以在运行时它会直接引用这个路径并访问文件,

您也可以添加这段代码来访问属性文件

is = ClassLoader.getSystemResourceAsStream("your_properties_file");

您可以相应地使用 load(is)

总结

如果您的 main 类在 src/main/java 中,那么您应该将您的属性文件保存在 src/main/resources 中并使用相应的代码段来加载它。

如果您的 main 类在 src/test/java 中,那么您应该将您的属性文件保存在 src/test/resources 中并使用相应的代码段来加载它。

答案 5 :(得分:0)

InputStream是= this.getClass()。getResourceAsStream(“ / package_name /属性文件名”)

PropertyFileOject.load(is)

在我的情况下,错误是由于maven没有将src / main / java中的config文件夹视为源文件夹。

在src / main / java中重新创建配置包。将文件复制到其中,然后使用maven重新编译。文件位于目标目录中,因此处于战争状态。错误已解决。

答案 6 :(得分:0)

最近,我遇到了同样的问题,并想到了解决方案,我不得不将资源放置在与getClass()。getResourceAsStream(name)所在位置相同的组织路径中。而且这样做之后我仍然有问题。后来,我发现创建一个包org.smth.smth只创建了一个名为“ org.smth.smth”的文件夹,而不是一个包含smth文件夹和smth内文件夹的文件夹org。路径结构解决了我的问题。希望这种解释是可以理解的。