從 Java 檔案 (JAR) 中讀取文件

Java 檔案 (Java Archive, JAR) 文件是基於 Java 技術的打包方案。它們容許開發人員把全部相關的內容 (.class、圖片、聲音和支持文件等) 打包到一個單一的文件中。JAR 文件格式支持壓縮、身份驗證和版本,以及許多其它特性。html

從 JAR 文件中獲得它所包含的文件內容是件棘手的事情,但也不是不能夠作到。這篇技巧就將告訴你如何從 JAR 文件中取得一個文件。咱們會先取得這個 JAR 文件中的文件目錄,而後讀取指定的文件。java

若是你熟悉常見的 ZIP 格式,你會發現 JAR 文件和它區別不大。JAR 文件提供了一個把多個文件打包到一個文件中的方法,並且被打包的每一個文件均可以分別壓縮。JAR 文件能夠添加一個被稱爲 manifest  的東西,它們容許開發人員添加與內容有關的其它信息。例如,manifest 能夠指明由 JAR 文件中的哪個文件開始運行應用程序,或者指定這個庫的版本等。安全

Java 2 SDK 標準版提供了一個 jar 工具,你能夠經過它在控制檯下讀寫 JAR 文件。而後,也許有些時候你想在你的程序中讀寫 JAR 文件。(這篇技巧僅涉及了在程序中讀 JAR 文件的內容。)很是高興,你能夠作到,而且不須要考慮解壓的問題,由於類庫已經幫你處理了。你要用到的類都在 java.util.jar 包中。這裏要用到的主要的類是 JarFile 類,它是一個 .jar 文件自身的引用。其中的每一個文件則由 JarEntry 引用。ide

如今開始,傳遞一個參數給 JarFile 的構造函數建立一個 JarFile 實例,這個參數多是 String 也能夠是 File,它是一個 .jar 文件的位置:函數

JarFile jarFile = new JarFile("thefile.jar");
或者
File file = new File("thefile.jar");
JarFile jarFile = new JarFile(file);工具

它還有其它一些構造函數,支持身份驗證和標記文件爲刪除。不過這裏不會涉及到這些構造函數。ui

在你獲得一個 JAR 文件的引用以後,你就能夠讀了其內容的目錄了。JarFile 的 entries 方法返回一個全部條目的 Enumeration 對象,你還能夠從 manifest 文件中得到它的屬性、身份驗證信息以及其它的信息,如條目的名稱和大小。spa

//  譯者注:enum 在 Java 5.0 中是關鍵字,因此該例在 5.0 中應該編譯失敗
//  但英文原著發表於 Java 5.0 出現以前,因此可使用 enum 做變量名
//  爲忠於原著,這裏未做修改
Enumeration  enum   =  jarFile.entries();
while  ( enum .hasMoreElements()) {
    process(
enum .nextElement());
}

之前提到過,每一個個體都是一個 JarEntry。這個類有一些諸如 getName、getSize 和getCompressedSize 的方法。

讓咱們舉例說明如何在程序中使用這些特性。下面的程序顯示 JAR 文件的內容列表及各項的名稱、大小和壓縮後的大小。(這很相似於使用帶 "t" 和 "v" 參數的 jar 命令。).net

import  java.io. * ;
import  java.util. * ;
import  java.util.jar. * ;

public   class  JarDir  {
    
public static void main (String args[]) 
        
throws IOException {
        
if (args.length != 1{
            System.out.println(
"Please provide a JAR filename");
            System.exit(
-1);
        }

        JarFile jarFile 
= new JarFile(args[0]);
        Enumeration 
enum = jarFile.entries();
        
while (enum.hasMoreElements()) {
            process(
enum.nextElement());
        }

    }


    
private static void process(Object obj) {
        JarEntry entry 
= (JarEntry)obj;
        String name 
= entry.getName();
        
long size = entry.getSize();
        
long compressedSize = entry.getCompressedSize();
        System.out.println(name 
+ " " + size + " " + compressedSize);
    }

}

若是你用 J2SE 1.4.1 中的 jce.jar 來試驗上述的 JarDir 程序,你應該看像下面那樣的輸出 (在 ... 處應該顯示更多文件):

META-INF/MANIFEST.MF    5315    1910
META-INF/4JCEJARS.SF    5368    1958
META-INF/4JCEJARS.DSA   2207    1503
META-INF/       0       2
javax/  0       0
javax/crypto/   0       0
javax/crypto/interfaces/        0       0
javax/crypto/interfaces/DHKey.class     209     185
javax/crypto/interfaces/DHPublicKey.class       265     215
javax/crypto/interfaces/DHPrivateKey.class      267     215
javax/crypto/interfaces/PBEKey.class    268     224
javax/crypto/SecretKey.class    167     155
...

注意輸入內容頂部包含 META-INF 的那幾行,這是 menifest 和安全驗證信息。其中大小爲 0 的項不是文件,而是目錄。

要真正從 JAR 文件中讀取文件內容,你必須得到相應條目的 InputStream。這不一樣於 JarEntry。JarEntry 僅包括了入口信息,卻並未包含實際的內容。這很像 File 和 FileInputSteram 的區別。只訪問 File,永遠不會打開相應的文件,它只讀取在目錄中的信息。下面告訴你如何從一個條目獲得 InputStream:

InputStream input = jarFile.getInputStream(entry);

獲得輸入流以後,你只須要像讀其它流同樣讀它就好了。若是是一個文本流,要記得使用一個 Reader 來從流中獲取字符。而對於字節流,如圖片,則只好直接讀取。

下面的程序演示了從一個 JAR 文件中讀取內容。運行程序時,須要指定要從 JAR 文件中讀取的文件名,這個文件必須是文本文件類型。htm

import  java.io. * ;
import  java.util.jar. * ;

public   class  JarRead  {
    
public static void main (String args[]) 
        
throws IOException {
        
if (args.length != 2{
            System.out.println(
"Please provide a JAR filename and file to read");
            System.exit(
-1);
        }

        JarFile jarFile 
= new JarFile(args[0]);
        JarEntry entry 
= jarFile.getJarEntry(args[1]);
        InputStream input 
= jarFile.getInputStream(entry);
        process(input);
        jarFile.close();
    }


    
private static void process(InputStream input) 
        
throws IOException {
        InputStreamReader isr 
= 
            
new InputStreamReader(input);
        BufferedReader reader 
= new BufferedReader(isr);
        String line;
        
while ((line = reader.readLine()) != null{
            System.out.println(line);
        }

        reader.close();
    }

}

假設你有一個名爲 myfiles.jar 的 JAR 文件,其中有一個名爲 spider.txt 文本文件,再假設那個  pider.txt 包含以下文本:

The itsy bitsy spider 
Ran up the water spout
Down came the rain and
Washed the spider out 

運行下面的命令以顯示 JAR 文件中該文本文件的內容:

java JarRead myfiles.jar spider.txt

關於 JAR 文件更多的內容,請參閱 JAR file specification

相關文章
相關標籤/搜索