从 Java 档案(JAR) 中读取文件

简介:

Java 档案 (Java Archive, JAR) 文件是基于 Java 技术的打包方案。它们允许开发人员把所有相关的内容 (.class、图片、声音和支持文件等) 打包到一个单一的文件中。JAR 文件格式支持压缩、身份验证和版本,以及许多其它特性。

  从 JAR 文件中得到它所包含的文件内容是件棘手的事情,但也不是不可以做到。这篇技巧就将告诉你如何从 JAR 文件中取得一个文件。我们会先取得这个 JAR 文件中的文件目录,然后读取指定的文件。

  如果你熟悉常见的 ZIP 格式,你会发现 JAR 文件和它区别不大。JAR 文件提供了一个把多个文件打包到一个文件中的方法,而且被打包的每个文件都可以分别压缩。JAR 文件可以添加一个被称为 manifest 的东西,它们允许开发人员添加与内容有关的其它信息。例如,manifest 可以指明由 JAR 文件中的哪一个文件开始运行应用程序,或者指定这个库的版本等。

  Java 2 SDK 标准版提供了一个 jar 工具,你可以通过它在控制台下读写 JAR 文件。然后,也许有些时候你想在你的程序中读写 JAR 文件。(这篇技巧仅涉及了在程序中读 JAR 文件的内容。)非常高兴,你可以做到,并且不需要考虑解压的问题,因为类库已经帮你处理了。你要用到的类都在 java.util.jar 包中。这里要用到的主要的类是 JarFile 类,它是一个 .jar 文件自身的引用。其中的每个文件则由 JarEntry 引用。

  现在开始,传递一个参数给 JarFile 的构造函数创建一个 JarFile 实例,这个参数可能是 String 也可以是 File,它是一个 .jar 文件的位置:

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

  它还有其它一些构造函数,支持身份验证和标记文件为删除。不过这里不会涉及到这些构造函数。

  在你得到一个 JAR 文件的引用之后,你就可以读了其内容的目录了。JarFile 的 entries 方法返回一个所有条目的 Enumeration 对象,你还可以从 manifest 文件中获得它的属性、身份验证信息以及其它的信息,如条目的名称和大小。

 
  1. // 译者注:enum 在 Java 5.0 中是关键字,所以该例在 5.0 中应该编译失败  
  2. // 但英文原著发表于 Java 5.0 出现之前,所以可以使用 enum 作变量名  
  3. // 为忠于原著,这里未作修改  
  4. Enumeration enum = jarFile.entries();  
  5. while (enum.hasMoreElements()) {  
  6.     process(enum.nextElement());  

以前提到过,每个个体都是一个 JarEntry。这个类有一些诸如 getName、getSize 和getCompressedSize 的方法。

让我们举例说明如何在程序中使用这些特性。下面的程序显示 JAR 文件的内容列表及各项的名称、大小和压缩后的大小。(这很类似于使用带 "t" 和 "v" 参数的 jar 命令。)

 
  1. import java.io.*;  
  2. import java.util.*;  
  3. import java.util.jar.*;  
  4.  
  5. public class JarDir ...{  
  6.     public static void main (String args[])   
  7.         throws IOException ...{  
  8.         if (args.length != 1) ...{  
  9.             System.out.println("Please provide a JAR filename");  
  10.             System.exit(-1);  
  11.         }  
  12.         JarFile jarFile = new JarFile(args[0]);  
  13.         Enumeration enum = jarFile.entries();  
  14.         while (enum.hasMoreElements()) ...{  
  15.             process(enum.nextElement());  
  16.         }  
  17.     }  
  18.  
  19.     private static void process(Object obj) ...{  
  20.         JarEntry entry = (JarEntry)obj;  
  21.         String name = entry.getName();  
  22.         long size = entry.getSize();  
  23.         long compressedSize = entry.getCompressedSize();  
  24.         System.out.println(name + " " + size + " " + compressedSize);  
  25.     }  

如果你用 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 文件中读取的文件名,这个文件必须是文本文件类型。

 
  1. import java.io.*;  
  2. import java.util.jar.*;  
  3.  
  4. public class JarRead ...{  
  5.     public static void main (String args[])   
  6.         throws IOException ...{  
  7.         if (args.length != 2) ...{  
  8.             System.out.println("Please provide a JAR filename and file to read");  
  9.             System.exit(-1);  
  10.         }  
  11.         JarFile jarFile = new JarFile(args[0]);  
  12.         JarEntry entry = jarFile.getJarEntry(args[1]);  
  13.         InputStream input = jarFile.getInputStream(entry);  
  14.         process(input);  
  15.         jarFile.close();  
  16.     }  
  17.  
  18.     private static void process(InputStream input)   
  19.         throws IOException ...{  
  20.         InputStreamReader isr =   
  21.             new InputStreamReader(input);  
  22.         BufferedReader reader = new BufferedReader(isr);  
  23.         String line;  
  24.         while ((line = reader.readLine()) != null) ...{  
  25.             System.out.println(line);  
  26.         }  
  27.         reader.close();  
  28.     }  

假设你有一个名为 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



本文转自边城__ 51CTO博客,原文链接:http://blog.51cto.com/jamesfancy/843235,如需转载请自行联系原作者

相关文章
|
23天前
|
Java
java小工具util系列5:java文件相关操作工具,包括读取服务器路径下文件,删除文件及子文件,删除文件夹等方法
java小工具util系列5:java文件相关操作工具,包括读取服务器路径下文件,删除文件及子文件,删除文件夹等方法
58 9
|
24天前
|
监控 Java 应用服务中间件
高级java面试---spring.factories文件的解析源码API机制
【11月更文挑战第20天】Spring Boot是一个用于快速构建基于Spring框架的应用程序的开源框架。它通过自动配置、起步依赖和内嵌服务器等特性,极大地简化了Spring应用的开发和部署过程。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,特别是spring.factories文件的解析源码API机制。
64 2
|
3天前
|
Java
java实现从HDFS上下载文件及文件夹的功能,以流形式输出,便于用户自定义保存任何路径下
java实现从HDFS上下载文件及文件夹的功能,以流形式输出,便于用户自定义保存任何路径下
59 34
|
16天前
|
Java 开发者
修改JAR文件工具
本文介绍了一款名为JarEditor的IDEA插件,该插件允许用户直接对JAR包内的文件进行增删改查操作,无需先行解压。通过简单的安装与使用步骤,大大简化了传统上需要解压缩、反编译、重新编译及打包的过程。此外,JarEditor还支持对混淆过的JAR文件进行字节码级别的修改,并提供了强大的搜索功能,支持大小写、全词匹配和正则表达式搜索。对于开发者而言,这款插件无疑极大提高了处理JAR文件的效率和便捷性。
52 14
|
20天前
|
消息中间件 存储 Java
RocketMQ文件刷盘机制深度解析与Java模拟实现
【11月更文挑战第22天】在现代分布式系统中,消息队列(Message Queue, MQ)作为一种重要的中间件,扮演着连接不同服务、实现异步通信和消息解耦的关键角色。Apache RocketMQ作为一款高性能的分布式消息中间件,广泛应用于实时数据流处理、日志流处理等场景。为了保证消息的可靠性,RocketMQ引入了一种称为“刷盘”的机制,将消息从内存写入到磁盘中,确保消息持久化。本文将从底层原理、业务场景、概念、功能点等方面深入解析RocketMQ的文件刷盘机制,并使用Java模拟实现类似的功能。
38 3
|
24天前
|
Java 测试技术 Maven
Maven clean 提示文件 java.io.IOException
在使用Maven进行项目打包时,遇到了`Failed to delete`错误,尝试手动删除目标文件也失败,提示`java.io.IOException`。经过分析,发现问题是由于`sys-info.log`文件被其他进程占用。解决方法是关闭IDEA和相关Java进程,清理隐藏的Java进程后重新尝试Maven clean操作。最终问题得以解决。总结:遇到此类问题时,可以通过任务管理器清理相关进程或重启电脑来解决。
|
28天前
|
存储 缓存 安全
在 Java 编程中,创建临时文件用于存储临时数据或进行临时操作非常常见
在 Java 编程中,创建临时文件用于存储临时数据或进行临时操作非常常见。本文介绍了使用 `File.createTempFile` 方法和自定义创建临时文件的两种方式,详细探讨了它们的使用场景和注意事项,包括数据缓存、文件上传下载和日志记录等。强调了清理临时文件、确保文件名唯一性和合理设置文件权限的重要性。
50 2
|
1月前
|
存储 安全 Java
如何保证 Java 类文件的安全性?
Java类文件的安全性可以通过多种方式保障,如使用数字签名验证类文件的完整性和来源,利用安全管理器和安全策略限制类文件的权限,以及通过加密技术保护类文件在传输过程中的安全。
43 4
|
1月前
|
存储 Java API
Java实现导出多个excel表打包到zip文件中,供客户端另存为窗口下载
Java实现导出多个excel表打包到zip文件中,供客户端另存为窗口下载
41 4
|
1月前
|
Java 数据格式 索引
使用 Java 字节码工具检查类文件完整性的原理是什么
Java字节码工具通过解析和分析类文件的字节码,检查其结构和内容是否符合Java虚拟机规范,确保类文件的完整性和合法性,防止恶意代码或损坏的类文件影响程序运行。
40 5