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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/26347415/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-02 09:46:10  来源:igfitidea点击:

InputStream.getResourceAsStream() giving null pointer exception

javainputstream

提问by CodeMed

The line persistenceProperties.load(is);is throwing a nullpointerexceptionin the following method. How can I resolve this error?

该行在以下方法中persistenceProperties.load(is);抛出 a 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);
    }  

I have tried to experiment with this by moving the class that contains the method to various other locations within the application structure, and also by changing the line of code preceding the error in the following ways:

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

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

But the error is still thrown every time the method is called.

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

Here is a printscreen of the directory structure of the eclipse project. The class containing the method is called TestFunctions.java, and the location of persistence.propertiesis shown:

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



**EDIT: **

**编辑: **

As per feedback below, I changed the method to:

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

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

I also moved mainTest.TestFunctions.java to src/test/java. Together, these all cause the following new stack trace:

我还将 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.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  

回答by chiastic-security

Two things:

两件事情:

First, try a path of test/samples/...or /test/samples/...

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

Secondly, and much more importantly, don't ever, ever, ever write this:

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

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

All this says is: do some stuff, and if it goes wrong, then fail silently.That is never the right thing to do: if there's a problem, you want to know about it, rather than madly rushing on as if nothing had happened. Either do some sensible processing in your catchblock, or else don't have the try/catchand add a throws IOExceptionto your method signature so it can propagate upwards.

这一切说的是:做一些事情,如果出错,然后默默地失败这从来都不是正确的做法:如果有问题,你想知道它,而不是像什么也没发生一样疯狂地匆匆忙忙。要么在您的catch块中进行一些合理的处理,要么没有try/catch并将 a 添加throws IOException到您的方法签名中,以便它可以向上传播。

But at the moment, you're just sweeping things under the carpet.

但目前,你只是在地毯下扫东西。

回答by Sbodd

Short answer: Move persistence.propertiesto src/main/resources, have both Main.javaand TestFunctions.javain src/main/java, and use

简短的回答:移动persistence.propertiessrc/main/resources,既有Main.javaTestFunctions.javasrc/main/java和使用

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

to load the properties file.

加载属性文件。

Long answer with an explanation:

带有解释的长答案:

As others have hinted at - in a Maven project structure, you (typically) have two directory trees: /src/mainand /src/test. The general intent is that any "real" code, resources, etc should go in /src/main, and items that are test-only should go in /src/test. When compiled and run, items in the testtree generally have access to items in the maintree, since they're intended to test the stuff in main; items in the maintree, however, do not typically have access to items in the testtree, since it's generally a bad idea to have your "production" code depending on test stuff. So, since Main.javadepends on TestFunctions.java, and TestFunctions.javadepends on persistence.properties, if Main is in src/mainthen both TestFunctionsand persistence.propertiesneed to be as well.

正如其他人所暗示的那样 - 在 Maven 项目结构中,您(通常)有两个目录树:/src/main/src/test. 总的意图是任何“真实”的代码、资源/src/main等都应该放入,而仅供测试的项目应该放入/src/test。编译和运行时,test树中的项通常可以访问树中的项main,因为它们旨在测试 main 中的内容;main然而,树中的项目通常无法访问test树中的项目,因为根据测试内容使用“生产”代码通常是一个坏主意。所以,既然Main.java要看TestFunctions.java,而且TestFunctions.java要看persistence.properties,如果主要是在src/main那么这两个TestFunctionspersistence.properties需要成为好。

回答by JB Nizet

ClassLoader.getResourceAsStream()loads resources as it does for loading classes. It thus loads them from the runtime classpath. Not from the source directories in your project.

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

Your class Mainis in the package maintest, and its name is thus maintest.Main. I know that without even seeing the code because Main.javais under a directory named maintest, which is at directly under a source directory.

您的类Main在包中maintest,因此它的名称是maintest.Main。我知道甚至没有看到代码,因为Main.java它位于名为 的目录下,该目录maintest直接位于源目录下。

The persistence.properties file is directly under a source directory (src/test/resources). At runtime, it's thus at the root of the classpath, in the default package. Its name is thus persistence.properties, and not src/test/samples/peristence.properties. So the code should be

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

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

Nothing will ever be loadable from the samples directory, since thisdirectory is not under any source directory, and is thus not compiled by Eclipse, and is thus not available to the ClassLoader.

任何东西都不能从示例目录中加载,因为该目录不在任何源目录下,因此不是由 Eclipse 编译的,因此类加载器不可用。

回答by ursa

Your IDE works with two different scopes:

您的 IDE 可在两个不同的范围内工作:

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

Seems you are trying to execute you program from production scope, while persistence.properties file is placed into test scope.

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

How to fix:

怎么修:

  • Place your test into src/test/java or
  • Move persistence.properties into src/main/resources
  • 将您的测试放入 src/test/java 或
  • 将 persistence.properties 移动到 src/main/resources

回答by Deepali Maniyar

InputStream is = this.getClass().getResourceAsStream("/package_name/property file name")

InputStream is = this.getClass().getResourceAsStream("/package_name/属性文件名")

PropertyFileOject.load(is)

PropertyFileOject.load(is)

In my case error was due to maven was not treating my config folder inside src/main/java as source folder.

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

Recreated config package in src/main/java ..Copied files to it and re-compiled using maven. Files were there in target directory and hence in war. Error resolved.

在 src/main/java 中重新创建配置包..将文件复制到其中并使用 maven 重新编译。文件在目标目录中,因此在War中。错误已解决。

回答by FireAndBlood

I recently had the same problem and came upon the solution that I had to put my resources in a path the same way organized as where was getClass().getResourceAsStream(name) situated. And I still had a problem after doing that. Later on, I discovered that creating a package org.smth.smth only had created a folder named like that "org.smth.smth" and not a folder org with a folder smth and a folder inside smth... So creating the same path structure solved my problem. Hope this explanation is understandable enough.

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