java中URL和File的相互轉化

首先,想比較一下這兩者的不同。URL用於網絡,所以帶有明顯的protocol,而且對於中文及符號支持的很不好。File就是我們平常系統中的文件路徑了,對於中文及符號都支持,但是已經沒有protocol了。所以,雖然兩者都可以表示文件路徑,但是卻不能混用了。
典型的URL和File路徑的比較:
URL:file:/D:/my%20java/URL&FILE/%e5%9b%be%e7%89%87/tongji.jpg
File:D:/my java/URL&FILE/圖片/tongji.jpg
其實兩者是一個文件。

回到正題:
這是我在JDK5.0下找到的方法,JDK5.0以下不支持:
URL to File:
URL url=……;
File file=new File(url.toURI);

File to URL:
File file=……;
URL url=file.toURL();

 

++++++++++++++++++++++++++++

獲取JAVA路徑,包括CLASSPATH外的路徑

歸納一些網上取JAVA路徑的方法:
  註明:如果從ANT啓動程序,this.getClass().getResource("")取出來的比較怪,直接用JAVA命令行調試就可成功。
  
  得到classpath和當前類的絕對路徑的一些方法
  獲得CLASSPATH之外路徑的方法:
  URL base = this.getClass().getResource(""); //先獲得本類的所在位置,如/home/popeye/testjava/build/classes/net/
  String path = new File(base.getFile(), "../../../"+name).getCanonicalPath(); //就可以得到/home/popeye/testjava/name
  下面是一些得到classpath和當前類的絕對路徑的一些方法。你可能需要使用其中的一些方法來得到你需要的資源的絕對路徑。
  1.FileTest.class.getResource("")
  得到的是當前類FileTest.class文件的URI目錄。不包括自己!
  如:file:/D:/java/eclipse32/workspace/jbpmtest3/bin/com/test/
  2.FileTest.class.getResource("/")
  得到的是當前的classpath的絕對URI路徑。
  如:file:/D:/java/eclipse32/workspace/jbpmtest3/bin/
  3.Thread.currentThread().getContextClassLoader().getResource("")
  得到的也是當前ClassPath的絕對URI路徑。
  如:file:/D:/java/eclipse32/workspace/jbpmtest3/bin/
  4.FileTest.class.getClassLoader().getResource("")
  得到的也是當前ClassPath的絕對URI路徑。
  如:file:/D:/java/eclipse32/workspace/jbpmtest3/bin/
  5.ClassLoader.getSystemResource("")
  得到的也是當前ClassPath的絕對URI路徑。
  如:file:/D:/java/eclipse32/workspace/jbpmtest3/bin/
  
我推薦使用Thread.currentThread().getContextClassLoader().getResource("")來得到當前的classpath的絕對路徑的URI表示法。
  在Web應用程序中,我們一般通過ServletContext.getRealPath("/")方法得到Web應用程序的根目錄的絕對路徑。這樣,我們只需要提供相對於Web應用程序根目錄的路徑,就可以構建出定位資源的絕對路徑。
  注意點:
  1.儘量不要使用相對於System.getProperty("user.dir")當前用戶目錄的相對路徑。這是一顆定時炸彈,隨時可能要你的命。
  2.儘量使用URI形式
  的絕對路徑資源。它可以很容易的轉變爲URI,URL,File對象。
  3.儘量使用相對classpath的相對路徑。不要使用絕對路徑。使用上面ClassLoaderUtil類的public static URL getExtendResource(String relativePath)方法已經能夠使用相對於classpath的相對路徑定位所有位置的資源。
  4.絕對不要使用硬編碼的絕對路徑。因爲,我們完全可以使用ClassLoader類的getResource("")方法得到當前classpath的絕對路徑。
  使用硬編碼的絕對路徑是完全沒有必要的!它一定會讓你死的很難看!程序將無法移植!
  如果你一定要指定一個絕對路徑,那麼使用配置文件,也比硬編碼要好得多!
  當然,我還是推薦你使用程序得到classpath的絕對路徑來拼資源的絕對路徑。

=============================================================================

在開發java程序的過程中,我們經常要做的一件事就是獲取資源。那麼什麼是資源呢?說白了,在計算機裏那就是一堆數據。只是這堆數據對我們的java程序有多種表現形式,一般來說有File,URL,InputStream等等。而單就文件這一項就有很多種:配置文件,java類文件,jps文件,圖片、css、js文件等等。面對這林林總總的資源,我們在設計一個讀取資源的接口時,就需要針對不同形式的資源提供方法,這樣就導致我們的接口還是與實際的資源形式綁定在一起,未能完全的抽象。另外,在java程序中資源的存放位置也是各異的。有的存放在classpath中,有的存放在文件系統中,有的存放在web應用中。而對於不同位置的資源,java程序獲取這些資源的方法各有不同。 
A、獲取classpath中的資源: 
Java代碼 
URL url = this.getClass().getResource("resource_name");  
URL url = this.getClass().getClassLoader().getResource("resource_name");  
URL url = Thread.currentThread().getContextClassLoader().getResource("resource_name");  

那麼在jdk中爲什麼又提供了三種方式來獲取classpath下的資源呢?這其中是有些來頭的。 
第一行代碼中是利用Class類的實例來獲取,第二行代碼是使用加載當前類的classloader來獲取。看下jdk中的源代碼會發現class類的實例最後還是委託加載他的classloader來獲取資源的。 
Java代碼 
public java.net.URL getResource(String name) {  
    name = resolveName(name);  
    ClassLoader cl = getClassLoader0();  
    if (cl==null) {  
        // A system class.  
        return ClassLoader.getSystemResource(name);  
    }  
    return cl.getResource(name);  
}  

從上面的代碼中可以看出,對於資源的加載並沒有像類加載所採用的雙親委託機制。而是當前類的classloader不爲null的情況下先從當前類的classloader中加載資源。而只有當前類的classloader爲null的時候才從system classloader中去加載資源。這樣可以方便我們自定義配置類覆蓋一些默認配置。當然,j2se應用中如果沒有特別定製classloader時,我們自己寫的類都是被system classloader加載的。到底利用class去獲取資源和利用classloader去獲取資源有什麼區別呢?區別就在 resolveName(name)這個方法中。兩種方式對於資源名稱的表示方式不同。下面是一個簡單的包結構,/表示類路徑的根 
/ 
|-com.cn.test 
   |-Test.class 
   |-test2.txt  
|-test1.txt 
Java代碼 
// 獲取與當前類在同一個包下的資源  
URL url1 = this.getClass().getResource("test2.txt");  
// 獲取com.cn.test包下的資源,需加/  
URL url2 = this.getClass().getResource("/com/cn/test/test2.txt");  
// 獲取類路徑根下的資源  
URL url3 = this.getClass().getClassLoader().getResource("test1.txt");  
// 獲取包com.cn.test包下的資源  
URL url4 = this.getClass().getResource("com/cn/test/test2.txt");  

而第三利用當前線程的contextClassLoader來獲取資源的解釋可以參考我的另一篇 
B、獲取文件系統中的資源 
Java代碼 
// 1、獲得File對象  
File file = new File("test.txt");  
// 2、獲得File對象的字節流  
InputStream in = new FileInputStream(file);  

值得注意的是在File的構造函數File(String name) 中的name參數可以是相對路徑和絕對路徑。相對路徑是相對於System.getProperties("user.dir")的。
C、獲取web應用中的資源 
Java代碼 
servletContext.getResourceAsStream(resource_name);  

resource_names爲相對於webroot的路徑表示。例如獲取web.xml,resource_name表示爲"/WEB-INF/web.xml" 

    面對上面介紹的各種資源表現形式和存放位置,難道java中就沒有提供一個統一處理方式嗎?有,java.net.URL。 
從名稱上來看 URL(Uniform Resource Locator) 統一資源定位器。看起來很好很強大。但很多時候使用它並不能定位到我們需要的資源。 
    首先,它jdk中體統的URL能訪問的協議非常有限(當然可以進行擴展,不過很麻煩);常用的有http,file,ftp等等。並沒有提供對classpath和servletContext中的資源的獲取方法。 
    另外,它沒有提供判斷資源是否存在的方法。每次只有等我們真正去獲取資源的時候拋出異常才能知道資源無法獲取。 
    其次,URL這個類的職責未劃分清楚,既用來表示資源有用來獲取其資源。 

發佈了26 篇原創文章 · 獲贊 10 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章