從JAR包中獲取資源的方法


jungleford如是說



    可能有不少初學者會有這樣的困惑(以前我也有過):在你的代碼里調用了一些資源文件,如圖片,音樂等,在調試環境或單獨運行的時候可以正常顯示或播放,而一旦打包到jar文件中,這些東東就再也出不來了,除非把這個jar放到原來未打包以前的目錄下,但通常jar是單獨發布的。這里介紹一個解決這類問題的方法。

getResource和getResourceAsStream



    問題的根源還是在於老生常談的所謂class path,不信的話你在系統環境變量里的ClassPath加上你的jar文件,這下你就看得到你的圖片了!但單獨發布jar的話不可能指望每次都讓用戶為你的jar而專門修改classpath。那么有沒有什么辦法一勞永逸地搞定它呢?我們需要從類的裝載入手。先扯遠一點,在開發JSP之類的Web應用程序的時候要用到第三方的庫怎么辦?通常的做法是把這些庫(可以是class,也可以是jar)統統放到WEB-INF/lib/目錄下面,為什么這樣系統就認了呢?因為Web容器(譬如Tomcat)在裝載類的時候有自己的組織方式(可以參考Tomcat手冊 http://jakarta.apache.org/tomcat/tomcat-4.1-doc/class-loader-howto.html)。特別地,jar也是類裝載器的一個可訪問媒介,ClassLoader提供了兩個方法用於從裝載的類路徑中取得資源:

  1.     public URL getResource(String name);
  2.     public InputStream getResourceAsStream(String name);

這里name是資源的類路徑,它是相對與“/”根路徑下的位置。getResource得到的是一個URL對象來定位資源,而getResourceAsStream取得該資源輸入流的引用保證程序可以從正確的位置抽取數據。
    真正使用的不是ClassLoader的這兩個方法,而是Class的getResource和getResourceAsStream方法,因為Class對象可以從你的類得到(如YourClass.class或YourClass.getClass()),而ClassLoader則需要再調用一次YourClass.getClassLoader()方法,但根據JDK文檔的說法,Class對象的這兩個方法其實是“委托”(delegate)給裝載它的ClassLoader來做的,所以只需要使用Class對象的這兩個方法就可以了。
    在參考資料中有一篇老外寫的文章比較深入介紹了從jar中裝載資源的方法。

一個應用的例子



    以下是在我寫的一個小工具 MSNHistoryCombiner中用到的一段代碼,可以從jar中裝載圖片和文本信息。譬如,你的jar中根目錄下有個img目錄,里面放有一些圖片,如img1.jpg,你可以這樣調用

  1.     Utilities.getImageFromJar("/img/img1.jpg", YourClass.class);

注意必須這里是“/img/img1.jpg”而非“img/img1.jpg”。從jar中讀文本資源也是類似方法調用getTextFromJar。
    需要說明的是,這段代碼也不是我原創的,是從一段別的代碼中經過修改得到的,但原代碼的來源忘記了,在這里向原作者表示感謝和歉意。

  1. import java.io.*;
  2. import java.awt.*;
  3. public class Utilities
  4. {
  5.   /**
  6.    * <p>
  7.    * Description: Return an Image based on the supplied image identifier. The
  8.    * image is assumed to reside at the defined location within the same
  9.    * repository as this class.
  10.    */
  11.   public static Image getImageFromJar(final String imageId, Class c)
  12.   {
  13.     // Image reference initialised to null (the image may not be found).
  14.     Image image = null;
  15.     // Open a resource stream on the supplied image identifier.
  16.     final InputStream inputStream = c.getResourceAsStream(imageId);
  17.     // If the image data is found...
  18.     if (inputStream != null)
  19.     {
  20.       // Open a byte array output stream so that we can create a byte
  21.       // array with which to create the image.
  22.       final ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
  23.       // Attempt to copy the source image data into the byte array
  24.       // stream, and then create an image from the result.
  25.       try
  26.       {
  27.         // Read/write image data in 1k chunks.
  28.         final byte[] bytes = new byte[1024];
  29.         int read = 0;
  30.         while ((read = inputStream.read(bytes)) >= 0)
  31.         {
  32.           byteArrayOutputStream.write(bytes, 0, read);
  33.         }
  34.         // Create an image from the resulting byte array.
  35.         image = Toolkit.getDefaultToolkit().createImage(
  36.             byteArrayOutputStream.toByteArray());
  37.       }
  38.       catch (IOException exception)
  39.       {
  40.         exception.printStackTrace();
  41.       }
  42.     }
  43.     return image;
  44.   }
  45.   public static String getTextFromJar(final String filename, Class c)
  46.   {
  47.     String text = "";
  48.     // Open a resource stream on the supplied file name.
  49.     final InputStream inputStream = c.getResourceAsStream(filename);
  50.     // If the file is found...
  51.     if (inputStream != null)
  52.     {
  53.       final BufferedReader in = new BufferedReader(new InputStreamReader(
  54.           inputStream));
  55.       try
  56.       {
  57.         String s;
  58.         while ((s = in.readLine()) != null)
  59.         {
  60.           text += s + "/n";
  61.         }
  62.       }
  63.       catch (IOException exception)
  64.       {
  65.         exception.printStackTrace();
  66.       }
  67.     }
  68.     return text;
  69.   }
  70. }

注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2019 ITdaan.com

赞助商广告