1. 程式人生 > 其它 >java當前路徑和相對路徑相關的疑惑

java當前路徑和相對路徑相關的疑惑

技術標籤:javajava

原文:https://blog.csdn.net/haoyifen/article/details/52733371

讓人迷惑的相對路徑

Java 中有一個很容易讓人誤解的問題, 就是路徑問題.
我們來看一段程式碼.
專案路徑為 /home/pathExample, 類的全限定名是 org.haoyifen.PathTest, 類的絕對地址為 /home/pathExample/src/main/java/org/haoyifen/PathTest.java

    public class PathTest {
        @Test
        public void relativePath
() { Path path = Paths.get("books.xml"); Path absolutePath = path.toAbsolutePath(); System.out.println(absolutePath); } }

初學者可能以為上面輸出的 * /home/pathExample/src/main/java/org/haoyifen/books.xml* , 但其實輸出的是 * /home/pathExample/books.xml* , 也就是相對於專案目錄.
這說明 Java 類中處理相對路徑並不是以當前該類的路徑來進行相對的, 這一點不同於 HTML 中的 js 檔案和 CSS 檔案的引用.

原因

其實 Java 中處理相對路徑是以 JDK 執行時的屬性”user.dir” 來進行相對的. 我們可以改變”user.dir” 對應的值, 來改變相對路徑轉換為絕對路徑的值.

        @Test
        public void changeUserDir() {
            //將user.dir對應的值設定為/home/haoyifen
            System.setProperty("user.dir", "/home/haoyifen");
            Path absolutePath = Paths.
get("books.xml").toAbsolutePath(); //驗證相對路徑轉換為絕對路徑時, 是以user.dir來進行計算的 Assert.assertEquals(absolutePath, Paths.get("/home/haoyifen/books.xml")); }

在不同的執行環境中, 比如開發時的 IDE, 執行時的命令列或者 WEB 容器, JDK 執行時的屬性”user.dir” 的值的改變規則都是不同的, Java 中絕對不要使用相對路徑來讀取檔案, 否則會出現開發時是正常的, 執行時就提示 java.io.FileNotFoundException: books.xml (沒有那個檔案或目錄)

類路徑和類載入器

Java中載入檔案, 最好是使用類路徑來進行載入, 以下是類路徑的一些規則 (假設類的全限定名為org.haoyifen.PathTest, 類的根路徑為/home/pathExample/target/classes)

  • PathTest.class.getResource(“”)
    當前類所在的目錄,file:/home/pathExample/target/classes/org/haoyifen/
  • PathTest.class.getResource(“/”)
    類的跟路徑, file:/home/pathExample/target/classes/
  • PathTest.class.getClassLoader().getResource(“”)
    類的跟路徑, file:/home/pathExample/target/classes/
  • Thread.currentThread().getContextClassLoader().getResource(“”)
    同上, 類的跟路徑, file:/home/pathExample/target/classes/

Spring 框架中的解決辦法

Spring 不僅僅適用於 Java SE, 也適用於 Java EE, Spring 中有個很重要的概念就是 Resource 介面, Resource 是一個抽象於底層實現的資源描述符, 用於獲取底層資源 (可以是檔案系統的 File 也可以是網路 URL) 的輸入流和其他相關資訊. 其中使用的最多的實現就是 ClassPathResource, 常見的使用案例有:

  • ClassPathXmlApplicationContext 載入 xml 配置檔案啟動 Spring 框架
  • Mybatis-Spring 中載入 Class 路徑中的 mapper.xml 檔案來生成 DAO

Resource 最重要的方法如下:

         */
        @Override
        public InputStream getInputStream() throws IOException {
            InputStream is;
            if (this.clazz != null) {
                is = this.clazz.getResourceAsStream(this.path);
            }
            else if (this.classLoader != null) {
                is = this.classLoader.getResourceAsStream(this.path);
            }
            else {
                is = ClassLoader.getSystemResourceAsStream(this.path);
            }
            if (is == null) {
                throw new FileNotFoundException(getDescription() + " cannot be opened because it does not exist");
            }
            return is;
        }
    

使用的就是 classLoader 來進行載入資源.

總結

  1. Java 中相對路徑是以 System.getProperty(“user.dir”) 來進行相對的.
  2. Java 中絕對不要使用相對路徑來載入檔案, user.dir 設定規則在 IDE, 命令列和 WEB 容器中是不同的.
  3. 使用類路徑或者類載入器來載入檔案, 這在 Java SE 專案和 WEB 容器中表現都是統一的.