這是一個(gè)古老的話(huà)題了,我曾經(jīng)寫(xiě)過(guò)一篇文章討論這個(gè)話(huà)題
http://blog.csdn.net/sunyujia/archive/2008/01/05/2027087.aspx
取得相對路徑的方法有很多,但是安全的方法并不多,我什么這么說(shuō)呢?
我先說(shuō)下一些流行方法的不安全性
轉載請注明出處http://blog.csdn.net/sunyujia/
1.new File(./xx.txt);或者是new File(xx.txt);
這種方法實(shí)際上是和window操作系統有關(guān)系的,對批處理和Win32編程有研究的朋友知道,運行一個(gè)程序要讓操作系統知道兩點(diǎn),1是文件存放的所在位置,2是文件的起始位置,這個(gè)起始位置很重要的,文件可以放置在C:\,而起始位置可以是D:\
感興趣的朋友可以試試新建立一個(gè)批處理test.bat
dir
pause
放置在c盤(pán)運行它,可以列出c盤(pán)的目錄
然后在這個(gè)批處理文件上面創(chuàng )建一個(gè)快捷方程式,然后右鍵->屬性->修改它的起始位置為d盤(pán)
點(diǎn)擊這個(gè)快捷方程式再看結果,如何?列出的是d盤(pán)的目錄.
所以在java中使用new File(xx.txt);是非常不安全的,因為.這個(gè)路徑的到底在哪里,取決于調用java 命令的起始位置定義在哪里.
tomcat/bin 下面的catalina.bat調用了java所以在tomcat環(huán)境下"."的位置就是tomcat/bin,但是eclipse啟動(dòng)程序,起始位置就是eclipse的項目路徑下了.不多說(shuō),大家已經(jīng)可以看出來(lái)了,這不是一個(gè)好方法.因為不能通過(guò)程序所在位置來(lái)確定一個(gè)路徑.
當然并不是說(shuō)這種方法就不可取,熟悉命令的朋友會(huì )想到在啟動(dòng)java.exe的時(shí)候將%CD%傳進(jìn)jvm里面,這是個(gè)方法,但是未免太麻煩了些.
2.類(lèi).class.getClassLoader().getResource("");
這也算是個(gè)比較流行的方法,但是使用它獲取相對路徑很不明朗,因為大部分情況我們希望相對路徑針對我們的class來(lái)說(shuō)是固定的,如果使用此方法,這把決定權交給了類(lèi)加載器,例如tomcat的類(lèi)加載是非委托機制的,而weblogic的類(lèi)加載是委托機制的,僅憑此一點(diǎn)就決定了,使用此方法不能保證在任何環(huán)境下,相對路徑是真正相對于class文件的.它是不安全的,不過(guò)大部分情況下它是安全的.我也在相當長(cháng)的一段時(shí)間內認為他是安全的,后來(lái)在weblogic的一個(gè)復雜類(lèi)加載器環(huán)境中發(fā)現它的不安全性.
3.類(lèi).class.getResource("")
看上去這確實(shí)是個(gè)好方法,但是它的局限性在于如果類(lèi)在jar中的話(huà),那么在打jar包的時(shí)候需要將文件夾也一起打進(jìn)去,否則會(huì )返回null,jar文件實(shí)際上就是zip文件,zip文件中:文件是文件,文件夾是文件夾,不是關(guān)聯(lián)在一起的,很多開(kāi)源的jar包就沒(méi)有把目錄打進(jìn)去只打了classes文件,雖然你能夠看到文件的目錄層次結構,但是調用類(lèi).class.getResource("")會(huì )返回null的.因為文件的目錄結構和文件夾本身是兩回事.對于這個(gè)問(wèn)題可追溯到我以前的一篇帖子http://topic.csdn.net/u/20080520/21/1dc25316-8316-46f8-904b-ded9c4b7587a.html
至于在web應用中取相對路徑的方法我就不說(shuō)了,因為他有局限性,我這里說(shuō)的都是在任何環(huán)境下都可以使用的方法.
取相對路徑最安全的的方法是什么呢?答案是取類(lèi)本身在系統中存儲的文件位置,然后根據包層次向上一直找到Classpath下面:實(shí)現非常簡(jiǎn)單,好了不多說(shuō)了放代碼:
package com.syj.util;
import java.io.File;
import java.io.UnsupportedEncodingException;
import java.net.URL;
/**
* <p>
* Title:URL輔助工具類(lèi)
* </p>
*
* <p>
* Copyright: 轉載請注明出處http://blog.csdn.net/sunyujia/
* </p>
*
* @author 孫鈺佳
* @main sunyujia@yahoo.cn
* @date Sep 21, 2008 12:31:23 PM
*/
public class URLUtil {
/**
*
* Description:取得當前類(lèi)所在的文件
*
* @param clazz
* @return
* @mail sunyujia@yahoo.cn
* @since:Sep 21, 2008 12:32:10 PM
*/
public static File getClassFile(Class clazz) {
URL path = clazz.getResource(clazz.getName().substring(
clazz.getName().lastIndexOf(".") + 1)
+ ".class");
if (path == null) {
String name = clazz.getName().replaceAll("[.]", "/");
path = clazz.getResource("/" + name + ".class");
}
return new File(path.getFile());
}
/**
*
* Description:同getClassFile 解決中文編碼問(wèn)題
*
* @param clazz
* @return
* @mail sunyujia@yahoo.cn
* @since:Sep 21, 2008 1:10:12 PM
*/
public static String getClassFilePath(Class clazz) {
try {
return java.net.URLDecoder.decode(getClassFile(clazz)
.getAbsolutePath(), "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
return "";
}
}
/**
*
* Description:取得當前類(lèi)所在的ClassPath目錄
*
* @param clazz
* @return
* @mail sunyujia@yahoo.cn
* @since:Sep 21, 2008 12:32:27 PM
*/
public static File getClassPathFile(Class clazz) {
File file = getClassFile(clazz);
for (int i = 0, count = clazz.getName().split("[.]").length; i < count; i++)
file = file.getParentFile();
if (file.getName().toUpperCase().endsWith(".JAR!")) {
file = file.getParentFile();
}
return file;
}
/**
*
* Description: 同getClassPathFile 解決中文編碼問(wèn)題
*
* @param clazz
* @return
* @mail sunyujia@yahoo.cn
* @since:Sep 21, 2008 1:10:37 PM
*/
public static String getClassPath(Class clazz) {
try {
return java.net.URLDecoder.decode(getClassPathFile(clazz)
.getAbsolutePath(), "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
return "";
}
}
public static void main(String[] args) throws UnsupportedEncodingException {
System.out.println(getClassFilePath(URLUtil.class));
System.out.println(getClassPath(URLUtil.class));
}
}
在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目錄.
大家可以在任意類(lèi)加載環(huán)境下進(jìn)行測試
原文網(wǎng)址:http://blog.csdn.net/sunyujia/archive/2008/09/21/2957481.aspx
聯(lián)系客服