通常獲取一個資源文件很簡單,問題是對於jar包內的資源文件,可能會發生意外。假如這里有一個文件操作的類:
public class FileLoader { public boolean exists(){ URL resource = FileLoader.class.getResource("/library/a.txt"); if(resource==null){ return false; } File f = new File(resource.getFile()); return f.exists(); } public static void main(String[] args) throws IOException { FileLoader f = new FileLoader(); System.out.println(f.exists()); } }
運行main方法它會讀取當前根路徑下(src/bin)的資源文件,假如存在目錄library和子文件a.txt,這里會打印出true;
現在把這段代碼和資源文件打成myfile.jar並運行在一個myeclipse工程中,我們期望也是打印true。然而控制台打印false;將其引入到war工程在tomcat中運行,依然打印false。
也就是說,資源文件的使用類無法找到自己,jar包正常的功能將無法提供。這是一個常見的關於jar路徑的問題。
為了試驗,在上面的FileLoader類中增加一個方法
public void printPath(){ System.out.println("/目錄: "+ FileLoader.class.getResource("/").getPath()); System.out.println("\"\"目錄: "+ FileLoader.class.getResource("").getPath()); System.out.println("/library目錄: "+ FileLoader.class.getResource("/library").getPath()); }
運行后打印結果為:
/目錄: /D:/Workspaces/ruleengine/file/target/classes/
""目錄: /D:/Workspaces/ruleengine/file/target/classes/com/file/
/library目錄: /D:/Workspaces/ruleengine/file/target/classes/library
重新打包后引入到一個當前myeclipse工程中,一定要以jar包的形式引入,不能通過myeclipse直接關聯myfile工程。調用printPath后打印結果為:
/目錄: /D:/Workspaces/ruleengine/schoolaround/target/test-classes/
""目錄: file:/D:/Workspaces/ruleengine/schoolaround/lib/myfile.jar!/com/file/
/library目錄: file:/D:/Workspaces/ruleengine/schoolaround/lib/myfile.jar!/library
顯而易見,獲取jar包中的文件路徑的格式已經變為*.jar!*(除了第一個),這種格式的路徑,不能通過new File的方式找到文件。目前本人也沒有找到其它處理方式,歡迎評論指點。在這種情況下,如果想讓jar讀取到自己的資源文件,可以通過類加載器的getResourceAsStream方法來解決。
修改FileLoader類的exists方法如下:
public boolean exists() throws IOException{ InputStream resource = FileLoader.class.getResourceAsStream("/library/a.txt"); if(resource==null){ return false; } return true; }
這時無論是在哪里引入myfile.jar,執行exists方法時都會打印true。也就是說,資源文件一定能夠被讀取到。
參考文章: https://blog.csdn.net/luo_jia_wen/article/details/50057191