原帖:http://zhangcong170.iteye.com/blog/850544
今天寫代碼的時候發現一個有趣的問題,就是在代碼中讀取一些資源文件(txt,gif等等)時候,單獨運行的時候,當然沒問題,但是當我們將項目打包成jar後,儘管資源文件在jar包內,但我們卻怎麼也訪問不到它了。
代碼結構如下:
- src|---com
- ---cn
- ---ChineseUtil.java
- src|---pinyin.txt
ChineseUtil.java
- package com.cn;
- import java.io.FileInputStream;
- import java.io.FileNotFoundException;
- import java.io.IOException;
- import java.io.InputStream;
- import java.net.URL;
- import java.util.Properties;
- public class ChineseUtil {
- private Properties properties;
- public ChineseUtil() {
- this.properties=loadProperties("pinyin.txt");
- }
- /**
- * 加載資源文件
- * @param file
- * @return
- */
- private Properties loadProperties(String file) {
- Properties p = new Properties();
- URL url=this.getClass().getResource("/"+file);
- System.out.println(url.getPath());//輸出文件路徑
- try {
- p.load(new FileInputStream(url.getFile()));
- } catch (FileNotFoundException e) {
- e.printStackTrace();
- } catch (IOException e) {
- e.printStackTrace();
- }
- return p;
- }
- }
在本工程下,測試代碼如下:
- public class PinyinTest {
- public static void main(String[] args) {
- ChineseUtil util=new ChineseUtil();
- }
- }
測試一切正常,沒有拋出異常,但是當我們將該項目打包成jar,新建一個java工程,並仍然採用上面的java代碼進行測試時,卻發現代碼拋出異常:
- file:/D:/frame/pinyin.jar!/pinyin.txt
- <span style="color: #ff0000;">java.io.FileNotFoundException: file:\D:\frame\pinyin.jar!\pinyin.txt (文件名、目錄名或卷標語法不正確。)</span>
拋出異常了,找不到資源文件了!讓我們注意一下輸出的文件的路徑,file:\D:\frame\pinyin.jar!\pinyin.txt,和一般的文件路徑相比,多了一個!,你不仔細觀察,是看不出來的!查閱了相關資料,原來jar包中文件URL有專用格式的:jar:<url>!/{entry},而我們是不能以這種形式來new一個File的,那該怎麼做呢,我們把 loadProperties方法修改如下:
- private Properties loadProperties(String file) {
- Properties p = new Properties();
- //注意加載資源文件的寫法 /表示從根目錄開始 否則就表示從當前類所在的路徑下開始
- InputStream is=this.getClass().getResourceAsStream("/"+file);
- try {
- p.load(is);
- } catch (FileNotFoundException e) {
- e.printStackTrace();
- } catch (IOException e) {
- e.printStackTrace();
- }
- return p;
- }
即通過通過Class類的getResourceAsStream()方法來獲取文件,這個方法是透明的,你可以像普通的File一樣去定位jar包中的資源文件(不管你是jar文件還是普通的文件夾)。另外還有一個比較讓人糾結的方式是使用java.util.jar.JarFile類才訪問,不過使用起來非常的不習慣,具體大家可以參考API試試。
PS:接下來該看看底層是怎麼實現了,有經驗的朋友不妨說說