Java InputStream.getResourceAsStream()提供空指针异常
行Java InputStream.getResourceAsStream()提供空指针异常,java,inputstream,Java,Inputstream,行persistenceProperties.load(is)正在以下方法中抛出nullpointerexception如何解决此错误? public void setUpPersistence(){ final Properties persistenceProperties = new Properties(); InputStream is = null; try { is = getClass().getClassLoader().getReso
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
两件事:
首先,尝试路径test/samples/…
或/test/samples/…
第二,更重要的是,永远,永远,永远不要写这封信:
try {
// some stuff
} catch (IOException ignored) {}
所有这一切都表明:做一些事情,如果出了问题,那么,默默地失败。这从来都不是正确的做法:如果有问题,你想知道,而不是像什么都没发生过一样疯狂地奔波。要么在catch
块中执行一些合理的处理,要么不要使用try
/catch
并向方法签名添加抛出IOException
,这样它就可以向上传播
但目前,您只是在掩盖事实。
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编译,因此类加载器无法使用它。您的IDE使用两种不同的作用域:
- 生产范围:src/main/java+src/main/resources文件夹和
- 测试范围:src/test/java+src/test/resources
- 将测试放入src/test/java或
- 将persistence.properties移到src/main/resources中
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
也需要在其中。InputStream=this.getClass().getResourceAsStream(“/package\u name/property file name”)
PropertyFileProject.load(is)
在我的例子中,错误是由于maven没有将src/main/java中的配置文件夹作为源文件夹处理
在src/main/java.中重新创建配置包。将文件复制到其中,并使用maven重新编译。文件位于目标目录中,因此处于战争状态。错误已解决。我最近遇到了相同的问题,并找到了解决方案,即我必须将资源放在一个路径中,路径的组织方式与getClass().getResourceAsStream(名称)所在的路径相同。但我还是有一个问题。后来,我发现创建一个包org.smth.smth只创建了一个名为“org.smth.smth”的文件夹,而不是一个包含文件夹smth和文件夹smth的文件夹org。。。因此,创建相同的路径结构解决了我的问题。希望这个解释可以理解。我会尽量让这个问题变得更简单 这里您的主类位于您提到的
src/main/java
中,因此您应该创建另一个存储属性文件的源代码,称为src/main/resources
,您已经这样做了,只需将属性文件存储在此源代码中,因此在运行时它将直接引用此路径并访问该文件
您也可以添加这段代码来访问属性文件
is=ClassLoader.getSystemResourceAsStream(“您的属性文件”)代码>
您可以使用load(is)