項目打包后運行報錯,找不到文件

我們常常在代碼中讀取一些資源文件(比如圖片漓糙,音樂铣缠,文本等等)。在單獨運行的時候這些簡單的處理當然不會有問題。但是蝗蛙,如果我們把代碼打成一個jar包以后蝇庭,即使將資源文件一并打包,這些東西也找不出來了哮内。看看下面的代碼:

  1. //源代碼1:
  2. package edu.hxraid;
  3. import java.io.*;
  4. public class Resource {
  5. public void getResource() throws IOException{
  6. File file=new File("bin/resource/res.txt");
  7. BufferedReader br=new BufferedReader(new FileReader(file));
  8. String s="";
  9. while((s=br.readLine())!=null)
  10. System.out.println(s);
  11. }
  12. }
    這段代碼寫在Eclipse建立的java Project中北发,其目錄為:(其中將資源文件res.txt放在了bin目錄下喷屋,以便打成jar包)
  1琳拨、src/
          src/edu/hxraid/Resource.java
  2、bin/
          bin/resource/res.txt
          bin/edu/hxraid/Resource.class

  很顯然運行源代碼1是能夠找到資源文件res.txt屯曹。但當我們把整個工程打成jar包以后(ResourceJar.jar),這個jar包內(nèi)的目錄為:
          edu/hxraid/Resource.class
          resource/res.txt

     而這時jar包中Resource.class字節(jié)碼:ldc <String "bin/resource/res.txt"> [20] 將無法定位到jar包中的res.txt位置上恶耽。就算把bin/目錄去掉:ldc <String "resource/res.txt"> [20] 仍然無法定位到jar包中res.txt上。

  **這主要是因為jar包是一個單獨的文件而非文件夾偷俭,絕對不可能通過"file:/e:/.../ResourceJar.jar/resource /res.txt"這種形式的文件URL來定位res.txt浪讳。所以即使是相對路徑,也無法定位到jar文件內(nèi)的txt文件(讀者也許對這段原因解釋有些費解涌萤,在下面我們會用一段代碼運行的結(jié)果來進一步闡述)。**

      那么把資源打入jar包形葬,無論ResourceJar.jar在系統(tǒng)的什么路徑下,jar包中的字節(jié)碼程序都可以找到該包中的資源。這會是幻想嗎冻辩?

  當然不是,我們可以用類裝載器(ClassLoader)來做到這一點:

     **(1) ClassLoader 是類加載器的抽象類倘感。它可以在運行時動態(tài)的獲取加載類的運行信息。 **可以這樣說老玛,當我們調(diào)用ResourceJar.jar中的Resource類時,JVM加載進Resource類蜡豹,并記錄下Resource運行時信息(包括Resource所在jar包的路徑信息)。而ClassLoader類中的方法可以幫助我們動態(tài)的獲取這些信息:
      ● public URL getResource(String name) 
        查找具有給定名稱的資源弄诲。資源是可以通過類代碼以與代碼基無關的方式訪問的一些數(shù)據(jù)(圖像娇唯、聲音、文本等)塔插。并返回資源的URL對象。
      ● public InputStream getResourceAsStream(String name); 
         返回讀取指定資源的輸入流留美。這個方法很重要伸刃,可以直接獲得jar包中文件的內(nèi)容。

      **(2) **ClassLoader是abstract的捧颅,不可能實例化對象,更加不可能通過ClassLoader調(diào)用上面兩個方法碉哑。**所以我們真正寫代碼的時候,是通過Class類中的getResource()和getResourceAsStream()方法妆毕,這兩個方法會委托ClassLoader中的getResource()和getResourceAsStream()方法 **贮尖。好了,現(xiàn)在我們重新寫一段Resource代碼,來看看上面那段費解的話是什么意思了:

Java代碼 [圖片上傳失敗...(image-2c71f2-1546854821835)] [圖片上傳中...(image-165870-1546854821835-4)] ?

  1. //源代碼2:

  2. package edu.hxraid;

  3. import java.io.*;

  4. import java.net.URL;

  5. public class Resource {

  6. public void getResource() throws IOException{

  7. //查找指定資源的URL薪前,其中res.txt仍然開始的bin目錄下

  8. URL fileURL=this.getClass().getResource("/resource/res.txt");

  9. System.out.println(fileURL.getFile());

  10. }

  11. public static void main(String[] args) throws IOException {

  12. Resource res=new Resource();

  13. res.getResource();

  14. }

  15. }

    運行這段源代碼結(jié)果:/E:/Code_Factory/WANWAN/bin/resource/res.txt (../ Code_Factory/WANWAN/.. 是java project所在的路徑)

      我們將這段代碼打包成ResourceJar.jar ,并將ResourceJar.jar放在其他路徑下(比如 c:\ResourceJar.jar)关斜。然后另外創(chuàng)建一個java project并導入ResourceJar.jar,寫一段調(diào)用jar包中Resource類的測試代碼:
    

Java代碼 [圖片上傳失敗...(image-c4b5c2-1546854821834)] [圖片上傳中...(image-f5f10a-1546854821834-2)] ?

  1. import java.io.IOException;

  2. import edu.hxraid.Resource;

  3. public class TEST {

  4. public static void main(String[] args) throws IOException {

  5. Resource res=new Resource();

  6. res.getResource();

  7. }

  8. }

       這時的運行結(jié)果是:file:/C:/ResourceJar.jar!/resource/res.txt
    
       我們成功的在運行時動態(tài)獲得了res.txt的位置垛膝。然而,問題來了倚聚,你是否可以通過下面這樣的代碼來得到res.txt文件扔罪?
                  File f=new File("C:/ResourceJar.jar!/resource/res.txt");
        當然不可能,因為".../ResourceJar.jar!/resource/...."并不是文件資源定位符的格式 (jar中資源有其專門的URL形式: **jar:<url>!/{entry}** )矿酵。所以,如果jar包中的類源代碼用File f=new File(相對路徑);的形式敞咧,是不可能定位到文件資源的辜腺。這也是為什么源代碼1打包成jar文件后,調(diào)用jar包時會報出FileNotFoundException的癥結(jié)所在了评疗。
    
      **(3) **我們不能用常規(guī)操作文件的方法來讀取ResourceJar.jar中的資源文件res.txt百匆,**但可以通過Class類的getResourceAsStream()方法來獲取 **,這種方法是如何讀取jar中的資源文件的加匈,這一點對于我們來說是透明的。我們將Resource.java改寫成:
    

Java代碼 [圖片上傳失敗...(image-cc880c-1546854821833)] [圖片上傳中...(image-42b01d-1546854821833-0)] ?

  1. //源代碼3:

  2. package edu.hxraid;

  3. import java.io.*;

  4. public class Resource {

  5. public void getResource() throws IOException{

  6. //返回讀取指定資源的輸入流

  7. InputStream is=this.getClass().getResourceAsStream("/resource/res.txt");

  8. BufferedReader br=new BufferedReader(new InputStreamReader(is));

  9. String s="";

  10. while((s=br.readLine())!=null)

  11. System.out.println(s);

  12. }

  13. }

      我們將java工程下/bin目錄中的edu/hxraid/Resource.class和資源文件resource/res.txt一并打包進ResourceJar.jar中,不管jar包在系統(tǒng)的任何目錄下,調(diào)用jar包中的Resource類都可以獲得jar包中的res.txt資源,再也不會找不到res.txt文件了。
    
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末甜橱,一起剝皮案震驚了整個濱河市栈戳,隨后出現(xiàn)的幾起案子难裆,更是在濱河造成了極大的恐慌镊掖,老刑警劉巖褂痰,帶你破解...
    沈念sama閱讀 219,110評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異归薛,居然都是意外死亡匪蝙,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,443評論 3 395
  • 文/潘曉璐 我一進店門千元,熙熙樓的掌柜王于貴愁眉苦臉地迎上來颤绕,“玉大人,你說我怎么就攤上這事奥务。” “怎么了挡篓?”我有些...
    開封第一講書人閱讀 165,474評論 0 356
  • 文/不壞的土叔 我叫張陵溢谤,是天一觀的道長。 經(jīng)常有香客問我阀参,道長瞻坝,這世上最難降的妖魔是什么蛛壳? 我笑而不...
    開封第一講書人閱讀 58,881評論 1 295
  • 正文 為了忘掉前任衙荐,我火速辦了婚禮浮创,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘斩披。我一直安慰自己讹俊,他們只是感情好煌抒,可當我...
    茶點故事閱讀 67,902評論 6 392
  • 文/花漫 我一把揭開白布寡壮。 她就那樣靜靜地躺著,像睡著了一般况既。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上坏挠,一...
    開封第一講書人閱讀 51,698評論 1 305
  • 那天降狠,我揣著相機與錄音,去河邊找鬼榜配。 笑死,一個胖子當著我的面吹牛临燃,可吹牛的內(nèi)容都是我干的烙心。 我是一名探鬼主播,決...
    沈念sama閱讀 40,418評論 3 419
  • 文/蒼蘭香墨 我猛地睜開眼爪瓜,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了铆铆?” 一聲冷哼從身側(cè)響起丹喻,我...
    開封第一講書人閱讀 39,332評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎谅猾,沒想到半個月后鳍悠,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體先煎,經(jīng)...
    沈念sama閱讀 45,796評論 1 316
  • 正文 獨居荒郊野嶺守林人離奇死亡巧涧,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,968評論 3 337
  • 正文 我和宋清朗相戀三年谤绳,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片缩筛。...
    茶點故事閱讀 40,110評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡堡称,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出桐臊,到底是詐尸還是另有隱情晓殊,我是刑警寧澤断凶,帶...
    沈念sama閱讀 35,792評論 5 346
  • 正文 年R本政府宣布认烁,位于F島的核電站介汹,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏嘹承。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,455評論 3 331
  • 文/蒙蒙 一舌镶、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧豪娜,春花似錦、人聲如沸瘤载。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,003評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至扣汪,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間冬筒,已是汗流浹背茅主。 一陣腳步聲響...
    開封第一講書人閱讀 33,130評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留诀姚,地道東北人。 一個月前我還...
    沈念sama閱讀 48,348評論 3 373
  • 正文 我出身青樓呀打,卻偏偏與公主長得像瑞佩,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子炬丸,可洞房花燭夜當晚...
    茶點故事閱讀 45,047評論 2 355

推薦閱讀更多精彩內(nèi)容