告別獲取不安全的相對路徑-取當前類的Classpath

這是一個古老的話題了,我曾經寫過一篇文章討論這個話題

http://blog.csdn.net/sunyujia/archive/2008/01/05/2027087.aspx 

取得相對路徑的方法有很多,但是安全的方法並不多,我什麼這麼說呢?

我先說下一些流行方法的不安全性

轉載請註明出處http://blog.csdn.net/sunyujia/

1.new File(./xx.txt);或者是new File(xx.txt);

這種方法實際上是和window操作系統有關係的,對批處理和Win32編程有研究的朋友知道,運行一個程序要讓操作系統知道兩點,1是文件存放的所在位置,2是文件的起始位置,這個起始位置很重要的,文件可以放置在C:/,而起始位置可以是D:/

感興趣的朋友可以試試新建立一個批處理test.bat

  1. dir 
  2. pause

放置在c盤運行它,可以列出c盤的目錄

然後在這個批處理文件上面創建一個快捷方程式,然後右鍵->屬性->修改它的起始位置爲d盤

點擊這個快捷方程式再看結果,如何?列出的是d盤的目錄.

所以在java中使用new File(xx.txt);是非常不安全的,因爲.這個路徑的到底在哪裏,取決於調用java 命令的起始位置定義在哪裏.

tomcat/bin 下面的catalina.bat調用了java所以在tomcat環境下"."的位置就是tomcat/bin,但是eclipse啓動程序,起始位置就是eclipse的項目路徑下了.不多說,大家已經可以看出來了,這不是一個好方法.因爲不能通過程序所在位置來確定一個路徑.

當然並不是說這種方法就不可取,熟悉命令的朋友會想到在啓動java.exe的時候將%CD%傳進jvm裏面,這是個方法,但是未免太麻煩了些.

2.類.class.getClassLoader().getResource("");

這也算是個比較流行的方法,但是使用它獲取相對路徑很不明朗,因爲大部分情況我們希望相對路徑針對我們的class來說是固定的,如果使用此方法,這把決定權交給了類加載器,例如tomcat的類加載是非委託機制的,而weblogic的類加載是委託機制的,僅憑此一點就決定了,使用此方法不能保證在任何環境下,相對路徑是真正相對於class文件的.它是不安全的,不過大部分情況下它是安全的.我也在相當長的一段時間內認爲他是安全的,後來在weblogic的一個複雜類加載器環境中發現它的不安全性.

3.類.class.getResource("")

看上去這確實是個好方法,但是它的侷限性在於如果類在jar中的話,那麼在打jar包的時候需要將文件夾也一起打進去,否則會返回null,jar文件實際上就是zip文件,zip文件中:文件是文件,文件夾是文件夾,不是關聯在一起的,很多開源的jar包就沒有把目錄打進去只打了classes文件,雖然你能夠看到文件的目錄層次結構,但是調用類.class.getResource("")會返回null的.因爲文件的目錄結構和文件夾本身是兩回事.對於這個問題可追溯到我以前的一篇帖子http://topic.csdn.net/u/20080520/21/1dc25316-8316-46f8-904b-ded9c4b7587a.html

至於在web應用中取相對路徑的方法我就不說了,因爲他有侷限性,我這裏說的都是在任何環境下都可以使用的方法.

取相對路徑最安全的的方法是什麼呢?答案是取類本身在系統中存儲的文件位置,然後根據包層次向上一直找到Classpath下面:實現非常簡單,好了不多說了放代碼:

  1. package com.syj.util;
  2. import java.io.File;
  3. import java.io.UnsupportedEncodingException;
  4. import java.net.URL;
  5. /**
  6.  * <p>
  7.  * Title:URL輔助工具類
  8.  * </p>
  9.  *
  10.  * <p>
  11.  * Copyright: 轉載請註明出處http://blog.csdn.net/sunyujia/
  12.  * </p>
  13.  *
  14.  * @author 孫鈺佳
  15.  * @main [email protected]
  16.  * @date Sep 21, 2008 12:31:23 PM
  17.  */
  18. public class URLUtil {
  19.     /**
  20.      *
  21.      * Description:取得當前類所在的文件
  22.      *
  23.      * @param clazz
  24.      * @return
  25.      * @mail [email protected]
  26.      * @since:Sep 21, 2008 12:32:10 PM
  27.      */
  28.     public static File getClassFile(Class clazz) {
  29.         URL path = clazz.getResource(clazz.getName().substring(
  30.                 clazz.getName().lastIndexOf(".") + 1)
  31.                 + ".class");
  32.         if (path == null) {
  33.             String name = clazz.getName().replaceAll("[.]""/");
  34.             path = clazz.getResource("/" + name + ".class");
  35.         }
  36.         return new File(path.getFile());
  37.     }
  38.     /**
  39.      *
  40.      * Description:同getClassFile 解決中文編碼問題
  41.      *
  42.      * @param clazz
  43.      * @return
  44.      * @mail [email protected]
  45.      * @since:Sep 21, 2008 1:10:12 PM
  46.      */
  47.     public static String getClassFilePath(Class clazz) {
  48.         try {
  49.             return java.net.URLDecoder.decode(getClassFile(clazz)
  50.                     .getAbsolutePath(), "UTF-8");
  51.         } catch (UnsupportedEncodingException e) {
  52.             e.printStackTrace();
  53.             return "";
  54.         }
  55.     }
  56.     /**
  57.      *
  58.      * Description:取得當前類所在的ClassPath目錄
  59.      *
  60.      * @param clazz
  61.      * @return
  62.      * @mail [email protected]
  63.      * @since:Sep 21, 2008 12:32:27 PM
  64.      */
  65.     public static File getClassPathFile(Class clazz) {
  66.         File file = getClassFile(clazz);
  67.         for (int i = 0, count = clazz.getName().split("[.]").length; i < count; i++)
  68.             file = file.getParentFile();
  69.         if (file.getName().toUpperCase().endsWith(".JAR!")) {
  70.             file = file.getParentFile();
  71.         }
  72.         return file;
  73.     }
  74.     /**
  75.      *
  76.      * Description: 同getClassPathFile 解決中文編碼問題
  77.      *
  78.      * @param clazz
  79.      * @return
  80.      * @mail [email protected]
  81.      * @since:Sep 21, 2008 1:10:37 PM
  82.      */
  83.     public static String getClassPath(Class clazz) {
  84.         try {
  85.             return java.net.URLDecoder.decode(getClassPathFile(clazz)
  86.                     .getAbsolutePath(), "UTF-8");
  87.         } catch (UnsupportedEncodingException e) {
  88.             e.printStackTrace();
  89.             return "";
  90.         }
  91.     }
  92.     public static void main(String[] args) throws UnsupportedEncodingException {
  93.         System.out.println(getClassFilePath(URLUtil.class));
  94.         System.out.println(getClassPath(URLUtil.class));
  95.     }
  96. }

 

在eclipse下執行

輸出爲

D:/SYJ.WORK/SYJ.WORKSPACE/ws1/util/classes/com/syj/util/URLUtil.class
D:/SYJ.WORK/SYJ.WORKSPACE/ws1/util/classes
打成jar包後在桌面下執行

輸出爲
file:/C:/Documents and Settings/Administrator/桌面/util.jar!/com/syj/util/URLUtil.class
file:/C:/Documents and Settings/Administrator/桌面

所取得的路徑一直都是class文件的classpath目錄.

大家可以在任意類加載環境下進行測試


 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章