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包文件内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!