簡體   English   中英

導出的JAR無法讀取本地文件

[英]Exported JAR unable to read local file

我的Java應用程序在名為“ assets”的頂級文件夾中有一個名為“ classes”(簡單的List<String> )的本地文件。 當我從Eclipse運行以下代碼時,讀取文件沒有問題。

try { // read in classes from local file
    ObjectInputStream inputStream =
            new ObjectInputStream(new FileInputStream("assets\\classes".replace("\\", "/")));
    listOfClasses = (List<String>) inputStream.readObject();
    System.out.println("*** Reading local copy of classes file ***");
    inputStream.close();
} catch (FileNotFoundException e) { e.printStackTrace();
} catch (ClassNotFoundException e) { e.printStackTrace();
} catch (IOException e) { e.printStackTrace(); }

當我將應用程序導出為JAR並在另一台計算機上運行時,在第三行顯示java.io.FileNotFoundException 我將“ assets”文件夾添加到了構建路徑,因此它應該在JAR中。

有人知道這是怎么回事嗎?

FileOutputStream只是打開一個本地文件。 它應該是絕對的( /home/user/...c:\\temp\\... )或相對於當前目錄。 例如,在Windows上,默認情況下就是包含JAR的目錄。

如果打算將classes文件打包 JAR中,則應使用getResourceAsStream ,如@guleryuz所述。 路徑應該是從CLASSPATH根目錄(即JAR文件的根目錄)開始的絕對路徑,例如"/asset‌​s/classes" ,或者相對於調用類的包而言是(更好)。

說到類,我強烈建議不要使用getClass()因為它是一種多態方法。 有兩種獲取類的方法:通過在對象上調用getClass()或通過訪問靜態class “字段”。 如果您有一個名為myObjectMyClass實例,則myObject.getClass()MyClass.class本質上是同一件事。 但! 如果你的類是由類從另一個包覆蓋,也就是說, TheirClass ,那么,對於實例TheirClassgetClass()將返回TheirClass.class ,即使您呼叫getClass()你的代碼。 因此,除非將您的類聲明為final ,否則使用getClass().getResource...始終是個壞主意getClass().getResource...因為您永遠不知道何時有人重寫您的類。 而且您不應該知道甚至不在乎!

假設所有這些,在名為my.package的包中就有一個名為MyClass的類。 JAR可以具有以下結構:

my/
    package/
        MyClass.class
        assets/
            classes

然后,調用MyClass.class.getResourceAsStream("assets/classes")應該可以解決問題。 另外,也可以是MyClass.class.getResourceAsStream("/my/package/assets/classes") 請注意,絕對路徑並非從項目目錄開始,您可能在其中有srcsrc/main或您的構建系統使用的任何目錄。 它是相對於CLASSPATH根目錄的(是的, 絕對路徑是對於CLASSPATH根目錄的,即使這聽起來很混亂)。 也就是說,它從您的軟件包所在的目錄開始。

最后但並非最不重要的一點是,如果您使用類似Maven的構建系統(例如,Maven或Gradle),則Java源代碼將轉到src/main/java ,而資源文件(如您的文件)將轉到src/main/resources 它們最終位於您的JAR文件中的完全相同的位置。 也就是說, src/main/java/package/MyClass.java被編譯為package/MyClass.class ,而src/main/resources/package/assets/classes進入package/assets/classes 但是,為了使構建系統確定如何處理文件,必須將它們放置在正確的目錄中: *.java轉到java ,資源轉到resources

因此,假設類似Maven的約定,則項目結構應為

src/
    main/
        java/
            my/
                package/
                    MyClass.java
src/
    main/
        resources/
            my/
                package/
                    assets/
                        classes

有了這樣的結構,您將獲得具有上述結構的JAR文件。 看起來有點瘋狂,但是一旦掌握了它,它就會非常有用。

如果您不使用類似Maven的構建系統,那么我不知道如何配置Eclipse。 不同的IDE可能有各自的約定,並且我一直將Maven與Eclipse結合使用。 例如,某些IDE喜歡將Java源和資源放入同一目錄樹中。

暫無
暫無

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

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