簡體   English   中英

InputStream.getResourceAsStream() 給出空指針異常

[英]InputStream.getResourceAsStream() giving null pointer exception

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  

簡短回答:將persistence.properties移動到src/main/resources ,在src/main/javaMain.javaTestFunctions.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那么TestFunctionspersistence.properties需要。

兩件事情:

首先,嘗試路徑test/samples/.../test/samples/...

其次,更重要的是,永遠不要寫這個:

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

所有這一切都說:做一些事情,如果出錯,然后默默地失敗 這從來都不是正確的做法:如果有問題,你想知道它,而不是像什么也沒發生一樣瘋狂地匆匆忙忙。 要么在你的catch塊中做一些合理的處理,要么沒有try / catch並在你的方法簽名中添加一個throws 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");

任何東西都不能從示例目錄加載,因為該目錄不在任何源目錄下,因此不是由 Eclipse 編譯的,因此類加載器不可用。

您的 IDE 可在兩個不同的范圍內工作:

  • 生產范圍:src/main/java + src/main/resources 文件夾和
  • 測試范圍:src/test/java + src/test/resources

似乎您正在嘗試從生產范圍執行您的程序,而將 persistence.properties 文件放入測試范圍。

怎么修:

  • 將您的測試放入 src/test/java 或
  • 將 persistence.properties 移動到 src/main/resources

我會盡量讓這個問題更簡單!

這里你的主類在你提到的src/main/java中,所以你應該創建另一個源來存儲你的屬性文件,說你已經完成的src/main/resources並將你的屬性文件存儲在這個源中,所以在 Run時間它會直接引用這個路徑並訪問文件,

您也可以添加這段代碼來訪問屬性文件

is = ClassLoader.getSystemResourceAsStream("your_properties_file");

並且您可以相應地使用load(is)

總結

如果您的main類在src/main/java那么您應該將屬性文件保存在src/main/resources並使用相應的代碼段來加載它。

或者

如果您的main類在src/test/java那么您應該將屬性文件保存在src/test/resources並使用相應的代碼段來加載它。

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

PropertyFileOject.load(is)

在我的情況下,錯誤是由於 maven 沒有將 src/main/java 中的 config 文件夾視為源文件夾。

在 src/main/java 中重新創建配置包..將文件復制到其中並使用 maven 重新編譯。 文件在目標目錄中,因此在戰爭中。 錯誤已解決。

我最近遇到了同樣的問題,並找到了一個解決方案,即我必須將我的資源放在與 getClass().getResourceAsStream(name) 所在位置相同的路徑中。 這樣做之后我仍然有問題。 后來,我發現創建一個包 org.smth.smth 只創建了一個名為“org.smth.smth”的文件夾,而不是一個文件夾 org,其中包含一個文件夾 smth 和一個文件夾在 smth 中......所以創建相同的路徑結構解決了我的問題。 希望這個解釋足夠好理解。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM