装饰器模式实现文件IO流的ZIP压缩解压(二)

时间:2021-05-12 21:37:41

      接着上篇文章,上一篇文章讲的是将一个文本文件的数据输出流,转换成ZIP的压缩输出流。

      这篇文章,讲述的是,怎样将上一篇文章中生成的压缩文件,进行解压的。也就是说,读取一个ZIP压缩文件,将里面一个被压缩的文件提取出来。

      其实,根据压缩、解压,输入、输出 我们可以写出四个装饰器类,分别完成IO流的输入输出、压缩解压功能。暂时先写两个,后面两个有时间再补。

package houlei.support.util.zip;

import java.io.IOException;
import java.io.InputStream;
import java.util.zip.CRC32;
import java.util.zip.CheckedInputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

/**
* 将一个ZIP输入流解压为普通的输入流,只解压其中的一个文件。
*/
public class ZipFileDecompressInputStream extends InputStream {

private ZipInputStream in = null;

/**
* 构建对象,完成转化。
* @param entryFileName 压缩包中保存文件的文件名
* @param inputStream 压缩包文件的输入流
*/
public ZipFileDecompressInputStream(String entryFileName, InputStream inputStream) throws IOException {
super();
CheckedInputStream cis = new CheckedInputStream(inputStream , new CRC32());
in = new ZipInputStream(cis);
ZipEntry entry = null;
while ((entry = in.getNextEntry()) != null) {
String name = entry.getName();
if(name==null && entryFileName==null){
break;
}
if(entryFileName!=null && entryFileName.equals(name)){
break;
}
in.closeEntry();
}
if(entry==null){
throw new IllegalArgumentException("解压的数据实体对象并不存在,entryFileName="+entryFileName);
}
}

@Override
public int read() throws IOException {
return in.read();
}

@Override
public void close() throws IOException {
try{
in.closeEntry();
}finally{
in.close();
}
}

/**
* 测试用例
*/
public static void main(String[] args) throws Exception{
final String file = "d:/tmp/1.zip";//待读取的压缩文件的文件名
final String entry = "text.txt";//压缩包内,待解压的文件名
java.io.InputStreamReader reader = null;
try {
reader = new java.io.InputStreamReader(new ZipFileDecompressInputStream(entry, new java.io.FileInputStream(file)));
char[] buff = new char[128];
int len =0;
while((len = reader.read(buff))>0){
System.out.print(String.valueOf(buff, 0, len));//打印文本文件的内容,这语句有编码BUG,只做测试使用。
}
} catch (IOException e) {
throw e;
} finally {
if(reader!=null){
reader.close();
}
}

}

}

看不懂测试用例的同学,我这里也再解释一下。

测试用例里面读取的是一个压缩文件。我们的程序以前可能是读取文本文件的,但是由于文本文件被ZIP压缩了,我们就得读取ZIP文件了。

如果没有包装输入流的话,我们应该读取没被压缩的文本文件,经过包装以后,我们可以读取压缩的ZIP文件了,

但是,只能读取压缩包中的一个文件内容,该文件的文件名在包装输入流的时候,通过参数传递进去了。

包装过后,我们发现,无论读取的是文本文件,还是ZIP压缩文件,我们对文件数据的处理代码,是不用修改的,

我们修改的只是读取的文件名,以及是否对文件输入流进行包装。