java读取zip/jar包中文件的几种方式

 更新时间:2023年07月25日 11:06:35   作者:赶路人儿  
这篇文章主要给大家介绍了关于java读取zip/jar包中文件的几种方式,在我们日常使用中压缩文件是非常常用的,文中通过示例代码将java读取zip/jar包中文件的方法介绍的非常详细,需要的朋友可以参考下

1、jar vs zip:

jar 文件和 zip 文件都是归档文件,并且都经过压缩。事实上,jar 文件使用与 zip 文件相同的存档和压缩技术,所以 jar 文件实际上是一种特定类型的 zip 文件。(JAR 文件本质上是一个包含可选 META-INF 目录的 zip 文件。)这一切都意味着:

  • 您可以使用与打开 zip 文件相同的工具打开 jar 文件
  • jar 文件是 zip 文件的子集,因此如果 zip 文件遵循 jar 规范,则它可以用作 jar 文件

2、读取zip压缩文件:

1)方法一:通过ZipFile从文件中读取

private static void readZipFile() {
    try (ZipFile zipFile = new ZipFile("/data/testzip.zip");) {
	    Enumeration<? extends ZipEntry> entries = zipFile.entries();
         while(entries.hasMoreElements()){
             ZipEntry entry = entries.nextElement();
		 System.out.println("fileName:"+entry.getName()); //文件名
		 InputStream stream = zipFile.getInputStream(entry); //读取文件内容
		 read(stream);
         }
    } catch(Exception e) {}
	//zipFile.close();
}
private static void read(InputStream in) { 
    try (InputStreamReader reader = new InputStreamReader(in, "UTF-8");
         BufferedReader br = new BufferedReader(reader);) {
         String con = null;
	      while ((con = br.readLine()) != null) {
	          System.out.println(con);
	      }
    } catch (Exception e) {}
}

2)方法二:通过ZipInputStream从流中读取

private static InputStream getInputStream() throws FileNotFoundException {
	File file = new File("/data/testzip.zip");
	InputStream in = new FileInputStream(file);
	return in;
}
//错误方法
private static void readZipInputStream() throws FileNotFoundException, IOException {
	InputStream zippedIn = getInputStream(); // zip压缩文件流
	ZipInputStream zis = new ZipInputStream(zippedIn);
	read(zis); //读取的是空
}
//正确方法
private static void readZipInputStream2() throws FileNotFoundException, IOException {
	InputStream zipFileInput = getInputStream(); // zip压缩文件流
	ZipInputStream zis = new ZipInputStream(zipFileInput);
	ZipEntry entry = null;
	try {
		while ((entry = zis.getNextEntry()) != null) {
			try {
				final String name = entry.getName();
				System.out.println("fileName:"+name);
				String content = IOUtils.toString(zis);
				System.out.println(content);
			} finally {
				zis.closeEntry(); // 关闭zipEntry
			}
		}
	} finally {
		zis.close(); //关闭zipInputStream
	}
}

注意:在从流中读取数据是使用了IOUtils,原因是自定义read方法读取完后会把传递进来的inputStream给关闭了。如果zip包中有多个文件,那么在读取第二个entry文件时就会报错。zipInputStream只能在最后关闭。而IOUtils使用了copy的方式,不会关闭传入的流。

3、jar中文件/目录便利,以及读取:

1)方法一:使用JarFile读取Jar文件

和ZipFile类似,使用'getEntry(String name)'或'entires'获得ZipEntry或JarEntry(它们可以看作同一东西),接下来使用" JarFile.getInputStream(ZipEntry ze)"将其用于获取InputStream

static void test1() {
    String path = "/Users/liuxiao/maven-rep/org/apache/thrift/libthrift/0.9.0/libthrift-0.9.0.jar";
    try (JarFile jarFile = new JarFile(new File(path));) {
        Enumeration<JarEntry> entries = jarFile.entries();
        while (entries.hasMoreElements()) {
            JarEntry entry = entries.nextElement();
            String entryName = entry.getName();
            if (!entry.isDirectory() && entryName.equals("org/apache/thrift/TBase.java")) {
                System.out.println(entryName);//  org/apache/thrift/EncodingUtils.class
                read(jarFile.getInputStream(entry));
            }
        }
    } catch (Exception e) {
    }
    //使用stream api
try (Stream<JarEntry> stream = new JarFile(new File(path)).stream();) {
        stream
            .filter(entry -> !entry.isDirectory() && entry.getName().endsWith(".class"))
            .forEach(entry -> System.out.println(entry.getName()));
    } catch(Exception e) {
    }
}

2)方法二:通过JarInputStream从流中读取(和ZipInputStream类似)

private static InputStream getJarFileInputStream() throws FileNotFoundException {
	File file = new File("/data/mvn_repo/commons-lang/commons-lang/2.1/commons-lang-2.1.jar");
	InputStream in = new FileInputStream(file);
	return in;
}
private static void readJarInputStream2() throws FileNotFoundException, IOException {
	InputStream zipFileInput = getJarFileInputStream(); // jar包流
	JarInputStream jis = new JarInputStream(zipFileInput);
	JarEntry entry = null;
	try {
		while ((entry = jis.getNextJarEntry()) != null) {
			try {
				if (entry.isDirectory()) {
					continue;
				}
				final String name = entry.getName();
				System.out.println("fileName:"+name);
				String content = IOUtils.toString(jis);
				System.out.println(content);
			} finally {
				jis.closeEntry(); // 关闭zipEntry
			}
		}
	} finally {
		jis.close(); //关闭zipInputStream
	}
}

3)方法三:通过JarURLConnection来打开一个jar中的资源,然后通过流来读取 

static void test2() throws Exception {
	String filePath = "/Users/liuxiao/maven-rep/org/apache/thrift/libthrift/0.9.0/libthrift-0.9.0.jar";
	String name = "org/apache/thrift/TBase.java";
	URL url = new URL("jar:file:" + filePath + "!/" + name);
	JarURLConnection jarConnection = (JarURLConnection) url.openConnection();
	try (InputStream in = jarConnection.getInputStream();
			BufferedReader br = new BufferedReader(new InputStreamReader(in, "UTF-8"));) {
		String con = null;
		while ((con = br.readLine()) != null) {
			System.out.println(con);
		}
	} catch (Exception e) {
		e.printStackTrace();
	}
}

总结:

由于zip和jar结构时一致的,所以ZipFile和JarFile,ZipInputStream和JarInputStream的使用方法是一样的。需要说明的一点是,由于zip包的这种特殊结构,默认ZipInputStream中是不包含数据的,只有在调用getNextEntry方法后,才回把对应的entry(zip包中的一个文件)内容写入到ZipInputStream中。上面的一个错误写法中,可以看到直接从ZipInputStream中读不到数据,只有调用getNextEntry后才可以。

到此这篇关于java读取zip/jar包中文件的几种方式的文章就介绍到这了,更多相关java读取zip/jar包文件内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Mybatis实现一对一查询映射处理

    Mybatis实现一对一查询映射处理

    MyBatis是一种流行的Java持久化框架,它提供了灵活而强大的查询映射功能,本文主要介绍了Mybatis实现一对一查询映射处理,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-08-08
  • 在dos窗口中编译和运行java文件的方法

    在dos窗口中编译和运行java文件的方法

    这篇文章主要介绍了在dos窗口中编译和运行java文件的方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-08-08
  • Java中方法的重写与成员变量的隐藏

    Java中方法的重写与成员变量的隐藏

    这篇文章讨论了Java面向对象概念中一个基本的概念–Field Hiding(隐藏成员变量),文中给大家介绍了java中的重写知识,非常不错,具有参考借鉴价值,需要的朋友参考下吧
    2017-11-11
  • java协程框架quasar和kotlin中的协程对比分析

    java协程框架quasar和kotlin中的协程对比分析

    这篇文章主要为大家介绍了java协程框架quasar和kotlin两个协程对比分析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多基本
    2022-02-02
  • SpringBoot使用AOP优雅实现系统操作日志的持久化

    SpringBoot使用AOP优雅实现系统操作日志的持久化

    在日常开发中,操作日志是系统不可或缺的一部分,本文将基于 AOP(面向切面编程) 思想,结合Spring生态,实现完整的操作日志方案,需要的小伙伴可以了解下
    2025-09-09
  • java父类和子类初始化顺序的深入理解

    java父类和子类初始化顺序的深入理解

    本篇文章是对java父类和子类初始化顺序进行了详细的分析介绍,需要的朋友参考下
    2013-06-06
  • 实现分布式WebSocket集群的方法

    实现分布式WebSocket集群的方法

    本文总结出了几个实现分布式WebSocket集群的办法,从zuul到spring cloud gateway的不同尝试,总结出了这篇文章,希望能帮助到某些人,并且能一起分享这方面的想法与研究
    2022-03-03
  • Java实现扑克牌的创建以及发放

    Java实现扑克牌的创建以及发放

    在java当中生成一副牌有很多种方法,有简单易于理解的面向过程编程,也有面向对象模块化编程,下面这篇文章主要给大家介绍了关于Java实现扑克牌的创建以及发放的相关资料,需要的朋友可以参考下
    2023-03-03
  • Java 中String StringBuilder 与 StringBuffer详解及用法实例

    Java 中String StringBuilder 与 StringBuffer详解及用法实例

    这篇文章主要介绍了Java 中String StringBuilder 与 StringBuffer详解及用法实例的相关资料,需要的朋友可以参考下
    2017-02-02
  • java分页之假分页实现简单的分页器

    java分页之假分页实现简单的分页器

    这篇文章主要介绍了java分页之假分页实现简单的分页器的相关资料,需要的朋友可以参考下
    2016-04-04

最新评论