Java 檔案 (Java Archive, JAR) 文件是基于 Java 技術(shù)的打包方案。它們?cè)试S開(kāi)發(fā)人員把所有相關(guān)的內(nèi)容 (.class、圖片、聲音和支持文件等) 打包到一個(gè)單一的文件中。JAR 文件格式支持壓縮、身份驗(yàn)證和版本,以及許多其它特性。
從 JAR 文件中得到它所包含的文件內(nèi)容是件棘手的事情,但也不是不可以做到。這篇技巧就將告訴你如何從 JAR 文件中取得一個(gè)文件。我們會(huì)先取得這個(gè) JAR 文件中的文件目錄,然后讀取指定的文件。
如果你熟悉常見(jiàn)的 ZIP 格式,你會(huì)發(fā)現(xiàn) JAR 文件和它區(qū)別不大。JAR 文件提供了一個(gè)把多個(gè)文件打包到一個(gè)文件中的方法,而且被打包的每個(gè)文件都可以分別壓縮。JAR 文件可以添加一個(gè)被稱(chēng)為 manifest 的東西,它們?cè)试S開(kāi)發(fā)人員添加與內(nèi)容有關(guān)的其它信息。例如,manifest 可以指明由 JAR 文件中的哪一個(gè)文件開(kāi)始運(yùn)行應(yīng)用程序,或者指定這個(gè)庫(kù)的版本等。
Java 2 SDK 標(biāo)準(zhǔn)版提供了一個(gè) jar 工具,你可以通過(guò)它在控制臺(tái)下讀寫(xiě) JAR 文件。然后,也許有些時(shí)候你想在你的程序中讀寫(xiě) JAR 文件。(這篇技巧僅涉及了在程序中讀 JAR 文件的內(nèi)容。)非常高興,你可以做到,并且不需要考慮解壓的問(wèn)題,因?yàn)轭?lèi)庫(kù)已經(jīng)幫你處理了。你要用到的類(lèi)都在 java.util.jar 包中。這里要用到的主要的類(lèi)是 JarFile 類(lèi),它是一個(gè) .jar 文件自身的引用。其中的每個(gè)文件則由 JarEntry 引用。
現(xiàn)在開(kāi)始,傳遞一個(gè)參數(shù)給 JarFile 的構(gòu)造函數(shù)創(chuàng)建一個(gè) JarFile 實(shí)例,這個(gè)參數(shù)可能是 String 也可以是 File,它是一個(gè) .jar 文件的位置:
JarFile jarFile = new JarFile("thefile.jar");
或者
File file = new File("thefile.jar");
JarFile jarFile = new JarFile(file);
它還有其它一些構(gòu)造函數(shù),支持身份驗(yàn)證和標(biāo)記文件為刪除。不過(guò)這里不會(huì)涉及到這些構(gòu)造函數(shù)。
在你得到一個(gè) JAR 文件的引用之后,你就可以讀了其內(nèi)容的目錄了。JarFile 的 entries 方法返回一個(gè)所有條目的 Enumeration 對(duì)象,你還可以從 manifest 文件中獲得它的屬性、身份驗(yàn)證信息以及其它的信息,如條目的名稱(chēng)和大小。
Enumeration enum = jarFile.entries();
while (enum.hasMoreElements()) {
process(enum.nextElement());
}
以前提到過(guò),每個(gè)個(gè)體都是一個(gè) JarEntry。這個(gè)類(lèi)有一些諸如 getName、getSize 和getCompressedSize 的方法。
記我們舉例說(shuō)明如何在程序中使用這些特性。下面的程序顯示 JAR 文件的內(nèi)容列表及各項(xiàng)的名稱(chēng)、大小和壓縮后的大小。(這很類(lèi)似于使用帶 "t" 和 "v" 參數(shù)的 jar 命令。)
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 + "\t" + size + "\t" + compressedSize);
}
}
如果你用 J2SE 1.4.1 中的 jce.jar 來(lái)試驗(yàn)上述的 JarDir 程序,你應(yīng)該看像下面那樣的輸出 (在 ... 處應(yīng)該顯示更多文件):
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
...
注意輸入內(nèi)容頂部包含 META-INF 的那幾行,這是 menifest 和安全驗(yàn)證信息。其中大小為 0 的條目不是文件,而是目錄。
要真正從 JAR 文件中讀取文件內(nèi)容,你必須獲得相應(yīng)條目的 InputStream。這不同于 JarEntry。JarEntry 僅包括了入口信息,卻并未包含實(shí)際的內(nèi)容。這很像 File 和 FileInputSteram 的區(qū)別。只訪(fǎng)問(wèn) File,永遠(yuǎn)不會(huì)打開(kāi)相應(yīng)的文件,它只讀取在目錄中的信息。下面告訴你如何從一個(gè)條目得到 InputStream:
InputStream input = jarFile.getInputStream(entry);
得到輸入流之后,你只需要像讀其它流一樣讀它就行了。如果是一個(gè)文本流,要記得使用一個(gè) Reader 來(lái)從流中獲取字符。而對(duì)于字節(jié)流,如圖片,則只好直接讀取。
下面的程序演示了從一個(gè) JAR 文件中讀取內(nèi)容。運(yùn)行程序時(shí),需要指定要從 JAR 文件中讀取的文件名,這個(gè)文件必須是文本文件類(lèi)型。
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();
}
}
假設(shè)你有一個(gè)名為 myfiles.jar 的 JAR 文件,其中有一個(gè)名為 spider.txt 文本文件,再假設(shè)那個(gè) pider.txt 包含如下文本:
The itsy bitsy spider
Ran up the water spout
Down came the rain and
Washed the spider out
運(yùn)行下面的命令以顯示 JAR 文件中該文本文件的內(nèi)容:
java JarRead myfiles.jar spider.txt
本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶(hù)發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)
點(diǎn)擊舉報(bào)。