从 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

相关文章
相关标签/搜索