Java相對路徑/絕對路徑總結


Version:0.9 StartHTML:-1 EndHTML:-1 StartFragment:00000099 EndFragment:00019826

Java相對路徑/絕對路徑總結(2)
修改瀏覽權限 | 刪除
歸納一些網上取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的絕對路徑來拼資源的絕對路徑。(T002)


java 使用相對路徑讀取文件

1.java project環境,使用java.io用相對路徑讀取文件的例子:
*目錄結構:
DecisionTree
           |___src
                |___com.decisiontree.SamplesReader.java
           |___resource
                |___train.txt,test.txt
*SamplesReader.java:
String filepath="resource/train.txt";//注意filepath的內容;
File file=new File(filepath);
……

*我們留意filepath的內容,java.io默認定位到當前用戶目錄("user.dir")下,即:工程根目

錄"D:\DecisionTree"下,因此,此時的相對路徑(以user.dir為基路徑的路徑)為"resource/train.txt"

。這樣,JVM就可以根據"user.dir"與"resource/train.txt"得到完整的路徑(即絕對路

徑)"D:\DecisionTree\resource\train.txt",從來找到train.txt文件。

*注意:相對路徑的起始處無斜桿"/";例如:
filepath="resource/train.txt";
而不是filepath="/resource/train.txt"; //error!

2、javaEE環境,使用Classloader用相對路徑讀取xml的例子:
*參見之前寫的文章“通過虛擬路徑或相對路徑讀取一個xml文件,避免硬編碼”。

*內容如下:
java使用相對路徑讀取xml文件:
一、xml文件一般的存放位置有三個:
1.放在WEB-INF下;
2.xml文件放在/WEB-INF/classes目錄下或classpath的jar包中;
3.放在與解析它的java類同一個包中,不一定是classpath;

二、相對應的兩種使用相對路徑的讀取方法:

方法一:(未驗證)
將xml文件放在WEB-INF目錄下,然后
程序代碼:
InputStream is=getServletContext().getResourceAsStream( "/WEB-INF/xmlfile.xml" );

方法二:將xml文件放在/WEB-INF/classes目錄下或classpath的jar包中,則可以使用ClassLoader的靜態

方法getSystemResourceAsStream(String s)讀取;
程序代碼:
String s_xmlpath="com/spf/web/ext/hotspot/hotspotxml/hotspot.xml";
InputStream in=ClassLoader.getSystemResourceAsStream(s_xmlpath);

方法三:xml在隨意某個包路徑下:
String s_xmlpath="com/spf/web/ext/hotspot/hotspotxml/hotspot.xml";
ClassLoader classLoader=HotspotXmlParser.class.getClassLoader();
InputStream in=classLoader.getResourceAsStream(s_xmlpath);


對於Java程序,無論是未打包的還是打包的JAR或WAR文件,有時候都需要獲取它運行所在目錄信息,如何做到這一點呢?

在Java處理的文件系統中,目錄的表示方式有兩種:

(1)絕對目錄,它以"/"為起始字符,代表從根目錄下開始尋找給出的目錄,如/c:/java

(2)相對路徑,它以不帶“/”的目錄名表示,表示以當前Java程序正在運行的目錄作為起始目錄來尋找給出的目錄。如java/classes。在相對路徑中,有一些特定的字符,可以代表特的的目錄,比如,“.”代表當前目錄,“..”代表當前目錄的上一級目錄。在網上很多給出的例子中,就是利用"."作為目錄名,構造File對象的實例,然后通過File對象的方法來獲取當前程序運行的目錄。

這種方法雖然簡單,但有時不能正確的得出當前程序的運行目錄。原因在於,運行Java程序不一定要進入到該程序的類文件或JAR文件所在的目錄,只要在運行時指定了正確的類路徑信息,就可以在任何目錄中運行Java程序,此時利用這種方法只能得到發出運行命令時所在的目錄信息。

從上面的分析可以看出,對於很多Java程序,尤其是WEB程序,利用當前路徑的“.”表示法,都不能滿足要求。那么怎樣才能正確的得到運行目錄信息呢?

在Web程序中,利用Servlet API可以獲得一些路徑信息,比如HttpServletRequest接口中定義的getRealPath方法,但類似這些方法都依賴於Servlet環境,不便於程序的單元測試。

本文提供了一種只使用Java標准API的路徑探測方法,就是利用ClassLoader抽象類。

利用java.lang.Class的getClassLoader方法,可以獲得給定類的ClassLoader實例,它的getResource方法可以獲得當前類裝載器中的資源的位置,我們可以利用類文件的名稱作為要查找的資源,經過處理后就可獲得當前Java程序的運行位置信息,其偽代碼如下:

獲得Class參數的所在的類名
取得該類所在的包名
將包名轉換為路徑
利用getResource得到當前的類文件所在URL
利用URL解析出當前Java程序所在的路徑

具體代碼如下:


Java代碼
/**-----------------------------------------------------------------------
*getAppPath需要一個當前程序使用的Java類的class屬性參數,它可以返回打包過的
*Java可執行文件(jar,war)所處的系統目錄名或非打包Java程序所處的目錄
*@param cls為Class類型
*@return 返回值為該類所在的Java程序運行的目錄
-------------------------------------------------------------------------*/    
public static String getAppPath(Class cls){    
   //檢查用戶傳入的參數是否為空    
   if(cls==null)    
    throw new java.lang.IllegalArgumentException("參數不能為空!");    
    ClassLoader loader=cls.getClassLoader();    
   //獲得類的全名,包括包名    
    String clsName=cls.getName()+".class";    
   //獲得傳入參數所在的包    
    Package pack=cls.getPackage();    
    String path="";    
   //如果不是匿名包,將包名轉化為路徑    
   if(pack!=null){    
        String packName=pack.getName();    
      //此處簡單判定是否是Java基礎類庫,防止用戶傳入JDK內置的類庫    
      if(packName.startsWith("java.")||packName.startsWith("javax."))    
         throw new java.lang.IllegalArgumentException("不要傳送系統類!");    
       //在類的名稱中,去掉包名的部分,獲得類的文件名    
        clsName=clsName.substring(packName.length()+1);    
       //判定包名是否是簡單包名,如果是,則直接將包名轉換為路徑,    
       if(packName.indexOf(".")<0) path=packName+"/";    
       else{//否則按照包名的組成部分,將包名轉換為路徑    
           int start=0,end=0;    
            end=packName.indexOf(".");    
           while(end!=-1){    
                path=path+packName.substring(start,end)+"/";    
                start=end+1;    
                end=packName.indexOf(".",start);    
            }    
            path=path+packName.substring(start)+"/";    
        }    
    }    
   //調用ClassLoader的getResource方法,傳入包含路徑信息的類文件名    
    java.net.URL url =loader.getResource(path+clsName);    
   //從URL對象中獲取路徑信息    
    String realPath=url.getPath();    
   //去掉路徑信息中的協議名"file:"    
   int pos=realPath.indexOf("file:");    
   if(pos>-1) realPath=realPath.substring(pos+5);    
   //去掉路徑信息最后包含類文件信息的部分,得到類所在的路徑    
    pos=realPath.indexOf(path+clsName);    
    realPath=realPath.substring(0,pos-1);    
   //如果類文件被打包到JAR等文件中時,去掉對應的JAR等打包文件名    
   if(realPath.endsWith("!"))    
        realPath=realPath.substring(0,realPath.lastIndexOf("/"));    
 /*------------------------------------------------------------
   ClassLoader的getResource方法使用了utf-8對路徑信息進行了編碼,當路徑
    中存在中文和空格時,他會對這些字符進行轉換,這樣,得到的往往不是我們想要
    的真實路徑,在此,調用了URLDecoder的decode方法進行解碼,以便得到原始的
    中文及空格路徑
  -------------------------------------------------------------*/    
 try{    
    realPath=java.net.URLDecoder.decode(realPath,"utf-8");    
   }catch(Exception e){throw new RuntimeException(e);}    
  return realPath;    
}//getAppPath定義結束    
/-----------------------------------------------------------------    
/**-----------------------------------------------------------------------
    *getAppPath需要一個當前程序使用的Java類的class屬性參數,它可以返回打包過的
    *Java可執行文件(jar,war)所處的系統目錄名或非打包Java程序所處的目錄
    *@param cls為Class類型
    *@return 返回值為該類所在的Java程序運行的目錄
    -------------------------------------------------------------------------*/
   public static String getAppPath(Class cls){
       //檢查用戶傳入的參數是否為空
       if(cls==null)
        throw new java.lang.IllegalArgumentException("參數不能為空!");
       ClassLoader loader=cls.getClassLoader();
       //獲得類的全名,包括包名
       String clsName=cls.getName()+".class";
       //獲得傳入參數所在的包
       Package pack=cls.getPackage();
       String path="";
       //如果不是匿名包,將包名轉化為路徑
       if(pack!=null){
           String packName=pack.getName();
          //此處簡單判定是否是Java基礎類庫,防止用戶傳入JDK內置的類庫
          if(packName.startsWith("java.")||packName.startsWith("javax."))
             throw new java.lang.IllegalArgumentException("不要傳送系統類!");
           //在類的名稱中,去掉包名的部分,獲得類的文件名
           clsName=clsName.substring(packName.length()+1);
           //判定包名是否是簡單包名,如果是,則直接將包名轉換為路徑,
           if(packName.indexOf(".")<0) path=packName+"/";
           else{//否則按照包名的組成部分,將包名轉換為路徑
               int start=0,end=0;
               end=packName.indexOf(".");
               while(end!=-1){
                   path=path+packName.substring(start,end)+"/";
                   start=end+1;
                   end=packName.indexOf(".",start);
               }
               path=path+packName.substring(start)+"/";
           }
       }
       //調用ClassLoader的getResource方法,傳入包含路徑信息的類文件名
       java.net.URL url =loader.getResource(path+clsName);
       //從URL對象中獲取路徑信息
       String realPath=url.getPath();
       //去掉路徑信息中的協議名"file:"
       int pos=realPath.indexOf("file:");
       if(pos>-1) realPath=realPath.substring(pos+5);
       //去掉路徑信息最后包含類文件信息的部分,得到類所在的路徑
       pos=realPath.indexOf(path+clsName);
       realPath=realPath.substring(0,pos-1);
       //如果類文件被打包到JAR等文件中時,去掉對應的JAR等打包文件名
       if(realPath.endsWith("!"))
           realPath=realPath.substring(0,realPath.lastIndexOf("/"));
     /*------------------------------------------------------------
      ClassLoader的getResource方法使用了utf-8對路徑信息進行了編碼,當路徑
       中存在中文和空格時,他會對這些字符進行轉換,這樣,得到的往往不是我們想要
       的真實路徑,在此,調用了URLDecoder的decode方法進行解碼,以便得到原始的
       中文及空格路徑
     -------------------------------------------------------------*/
     try{
       realPath=java.net.URLDecoder.decode(realPath,"utf-8");
      }catch(Exception e){throw new RuntimeException(e);}
      return realPath;
   }//getAppPath定義結束
  //-----------------------------------------------------------------
該方法既可以用於JAR或WAR文件,也可以用於非JAR文件。但要注意以下2點:


不要傳遞系統的類,作為getAppPath的參數,如java.lang.String.class,當然,也不要傳遞那些已經位於JDK中的那些類,比如xml相關的一些類等等。
要傳遞應該是程序中主要的運行類,不要傳遞程序中的支持類庫中的類文件,也就是那些第三方的類庫中的類文件,否則得到的將是那些類庫的位置。

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM