簡體   English   中英

通過Eclipse運行時,Java無法找到文件

[英]Java can't find file when running through Eclipse

當我運行應該從Eclipse中的文件讀取的Java應用程序時,我得到一個java.io.FileNotFoundException ,即使該文件位於正確的目錄中。 我可以從命令行編譯並運行應用程序就好了; 該問題僅發生在Eclipse中,具有多個項目和應用程序。 是否需要在運行配置或構建路徑中更改設置以使其正確查找文件?

問題很可能是您的應用程序使用的是相對路徑名。 正如@BalusC所說,相對路徑名可能會有問題。 但IMO,當他說“你永遠不應該在java.io的東西中使用相對路徑”時,他走得太遠了。

當應用程序使用(例如) FileInputStream(File)構造函數打開文件時,相對於“當前目錄”,相對於“當前目錄”,在File.getAbsolutePath()的javadoc中描述的過程中解析相對路徑名。

[...]否則,此路徑名將以系統相關的方式解析。 在UNIX系統上,通過將相對路徑名解析為當前用戶目錄,使其成為絕對路徑名。 在Microsoft Windows系統上,通過將路徑名解析為路徑名所指定的驅動器的當前目錄(如果有),使相對路徑名成為絕對路徑名; 如果沒有,則針對當前用戶目錄解析。

所以我們立即看到“當前目錄”的概念在Windows和UNIX平台上有不同的細微差別。 第二個問題是,在純Java中,您無法明確地找出當前目錄是什么,並且您當然無法使用純Java為當前JVM更改它。 (當JVM啟動時,“user.dir”系統屬性被設置為當前目錄,但沒有什么能阻止應用程序更改屬性,因此您無法完全依賴它。此外,更改“user.dir”只會更改解決空路徑的方式,而不是一般的相對路徑。)

那么你應該怎么做呢?

  • 一種選擇是使用絕對路徑名來引用文件。 這在(幾乎)所有情況下都是可靠的,但如果用戶必須輸入路徑名,或者如果您需要避免硬連線(或配置)的絕對路徑名,則使用絕對路徑名可能會有問題。

  • 第二種選擇是使用類路徑相對路徑名並找到相對於應用程序安裝目錄的文件。 如果您需要這樣做,這可以工作,但如果您需要將File傳遞給某個庫方法,則會出現問題。 如果您正在嘗試查找用戶的應用程序首選項,它也無濟於事。 (通常,將用戶首選項放入安裝目錄是錯誤的......)

  • 第三個選項是相對於從其他地方獲得的某個絕對目錄命名文件; 例如new File(System.getProperty("home.dir"), "foo/bar");

  • 最后一個選項是使用相對路徑名,並假設用戶知道當前目錄是什么。 對於用戶從命令行運行的許多應用程序,這是正確的解決方案。

在Eclipse的特定情況下,有一個簡單的解決方案。 轉到用於啟動應用程序的“運行配置”,打開“參數”選項卡,然后單擊“其他”單選按鈕。 然后輸入絕對路徑名作為已啟動應用程序的工作目錄。 啟動子JVM時,它將指定的工作目錄作為其當前目錄。

另一種選擇是簡單地找出“當前路徑”指向您環境中的目錄 - 無論是什么。 一旦你弄清楚,你可以從那里選擇你的解決方案。 也許這是使用適當的相對路徑到您的文件的位置或重新定位文件。

    File testFile = new File("");
    String currentPath = testFile.getAbsolutePath();
    System.out.println("current path is: " + currentPath);

在Eclipse中創建默認Java應用程序時,您將獲得以下目錄結構:

./ProjectName/ - 根目錄
./ProjectName/bin/ - 輸出目錄,包含.class文件
./ProjectName/src/ - 源目錄,包含.java文件

如果您的應用程序請求“./data.txt”,它將相對於根目錄搜索它。 這是“工作目錄”,可以根據Martin上面的回復在參數選項卡中進行配置。

你說它可以從命令行工作嗎? 這可能是因為您在運行java二進制文件時位於bin或src文件夾中。 在這種情況下,工作目錄是命令提示符當前所在的目錄。 例如,如果你進入/ src /目錄,說javac *.java然后從那里運行文件,它將在/ src /目錄中搜索“./data.txt”。 如果你進入/ bin /目錄並從那里運行你的應用程序,它將查找相對於/ bin /目錄的文件。

我遇到了類似的問題,我將文件放在src文件夾中名為cobolcopybooks的文件夾中,並嘗試使用classloader.getResource(“cobolcopybooks / demostud.cob”)在我的項目中訪問它們,但我得到空指針異常,我經過多次嘗試失敗后,通過清理和構建工作區幾次嘗試了幾次,我意識到我沒有刷新項目以允許文件與項目一起構建。 即這些文件應該與其他類文件一起可見,因為在運行時根目錄將是bin目錄,並且它在那里搜索那些文件。

永遠不應該在java.io使用相對路徑。 該路徑將依賴於當前工作目錄,這取決於您啟動應用程序的方式,因此在所有環境中本身並不相同。 這在Java應用程序內部是無法控制的。 便攜性問題! 始終使用絕對路徑。 例如c:/path/to/file.ext/path/to/file.ext (帶有前導斜杠)用於UNIX和consorts(當磁盤字母不相關時甚至是Windows)。

每當您想要將一些文件與應用程序一起發送時,通常的做法是將它們放在類路徑中。 這樣您就可以使用ClassLoader#getResource()來獲取其位置。 它返回一個URL 您可以使用URL#toURI()URL#getPath()並將其傳遞給java.io.File構造函數,然后以通常的方式進一步使用它。

在Eclipse項目中, src文件夾(Java源代碼所在的位置)基本上是類路徑的根。 此外,它當然還涵蓋了項目的構建路徑中的所有其他項目和(外部)文件夾。

假設您已將特定文件放在類路徑的根目錄中:

ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
URL url = classLoader.getResource("file.ext");
File file = new File(url.getPath());
FileInputStream input = new FileInputStream(file);
// ...

您甚至可以使用ClassLoader#getResourceAsStream()直接獲取InputStream

ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
InputStream input = classLoader.getResourceAsStream("file.ext");
// ...

如果它放在包中,那么你可以使用通常的路徑名:

URL url = classLoader.getResource("com/example/file.ext");
// ...

要么

InputStream input = classLoader.getResourceAsStream("com/example/file.ext");
// ...

假設用戶沒有輸入文件的完整文件路徑並輸入類似“myfilenameonly”的內容。 File file = new File(".", args[0])在這種情況下是必要的,以找到文件(注意傳遞的第一個參數)。

所有平台: File.getParent()不返回父目錄,它應以文件系統特定的方式返回“..”或父目錄的名稱。

如果創建文件“myfilenameonly”而未指定其所在目錄的完整路徑,則File.getParent()將返回null。

進一步了解: http//bugs.sun.com/bugdatabase/view_bug.do?video_id = 1228537

暫無
暫無

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

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