输入流(读取):
ZipInputStream是一种FileInputStream流,它可以直接读取Zip压缩包的内容:
┌───────────────────┐
│ InputStream │
└───────────────────┘
▲
│
┌───────────────────┐
│ FilterInputStream │
└───────────────────┘
▲
│
┌───────────────────┐
│InflaterInputStream│
└───────────────────┘
▲
│
┌───────────────────┐
│ ZipInputStream │
└───────────────────┘
▲
│
┌───────────────────┐
│ JarInputStream │
└───────────────────┘
另一个JarInputstream是从ZipInputStream派生出来的,它增加的主要功能是直接读取jar文件里面的MANIFEST.MF文件。因为本质上jar包就是zip包,只是额外增加了一些固定的描述文件。
根据上述继承关系,最终还是回到了Inputstream这个抽象类中。而Java的IO标准库使用Decorator装饰器模式为Inputstream和OutputStream增加功能:
可以把一个Inputstream和任意一个FilterInputStream组合。
可以把一个OutputStream和任意一个FilterOutputStream组合。
通过装饰器模式也就可以使用ZipInputStream来操作ZIP文件了。
ZipInputstream的基本用法是:
创建一个ZipInputstream对象,传入一个FileInputstream作为数据源,然后调用getNextEntry()方法,直到返回值为null,表示zip流结束。
一个ZipEntry表示一个压缩文件或目录,如果是压缩文件,我们就用read()方法不断读取,直到返回-1:
package com.apesource;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
public class Demo02 {
public static void main(String[] args) {
try (ZipInputStream zip = new ZipInputStream(new FileInputStream("d:\\IOTest\\1-201023201325.zip"),
Charset.forName("gbk"))) {
ZipEntry entry = null;
// 获取压缩文件中的每个子文件
while ((entry = zip.getNextEntry()) != null) {
System.out.println(entry.getName());
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
输出流(写入):
也称为压缩流,它用于以zip格式写入文件,也就是把文件打包成压缩文件,常用于附件下载,文件压缩存储。
┌───────────────────┐
│ OutputStream │
└───────────────────┘
▲
│
┌───────────────────┐
│ FilterInputStream │
└───────────────────┘
▲
│
┌────────────────────┐
│DeflaterOutputStream│
└────────────────────┘
▲
│
┌───────────────────┐
│ ZipInputStream │
└───────────────────┘
▲
│
┌───────────────────┐
│ JarOutputStream │
└───────────────────┘
压缩流常用的两个方法为:
①:
// 开始写入新的 ZIP 文件条目并将流定位到条目数据的开头。如果仍处于活动状态,则关闭当前条目。
// 这里的ZipEntry就是一个条目
// 条目类:ZipEntry(表示 ZIP 文件条目)
public void putNextEntry(ZipEntry e) throws IOException {}
②:
// 关闭当前 ZIP 条目并定位流以写入下一个条目
public void closeEntry() throws IOException {}
ZipOutputStream可以把多份数据写入zip包
先创建一个ZipOutputStream对象,从中包装一个FileOutputStream流,然后每写入一个文件(条目类),先调用putNextEntry(),然后write()写入byte[]数据,写入完毕后调用closeEntry()方法结束这个文件的打包。
具体实现代码如下:
package com.apesource;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
/**
* 将指定文件写入zip文件
* @author wyh
*
*/
public class Demo02 {
public static void main(String[] args) {
// 原始目录
File rootDir = new File("d:\\IOTest\\tuji");
// 将原始目录中的文件,“写入”zip压缩文件
try (ZipOutputStream out = new ZipOutputStream(new FileOutputStream(rootDir.getParent() + "\\" + rootDir.getName() + ".zip"))) {
// 获取并遍历原始目录下的子文件列表
File[] files = rootDir.listFiles();
// 循环写入每一个文件
for (File f : files) {
// 创建一个ZipEntry
out.putNextEntry(new ZipEntry(f.getName()));
// 将源文件的字节内容,写入zip压缩包
out.write(Files.readAllBytes(f.toPath()));
// 结束当前zipEntry
out.closeEntry();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}