以前项目中需要下载一个数据库导出的SQL文本文件到客户电脑,但是这个文件体积庞大,有一个多G的样子,客户只有200KB的带宽,传输非常慢。
于是,对服务端的下载程序,做了一个简单的调整,使得客户接收到的数据,是已经压缩后的ZIP文件。
下面介绍代码,里面包含测试用例。该代码只支持一个ZIP压缩包中,只有一个被压缩的文件,暂不支持多个文件的情况。因为当时场景不需要。
package houlei.support.util.zip;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.zip.CRC32;
import java.util.zip.CheckedOutputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
/**
* 将一个输出流,转换成ZIP输出流,其中,源输出流作为压缩流中的一个文件。
*/
public class ZipFileCompressOutputStream extends OutputStream {
private ZipOutputStream zipOut;
/**
* 构建对象,完成转化。
* @param entryFileName 压缩包中保存文件的文件名
* @param out 压缩包文件的输出流
*/
public ZipFileCompressOutputStream(String entryFileName, OutputStream out) throws IOException {
ZipEntry e = new ZipEntry(entryFileName);
CheckedOutputStream cos = new CheckedOutputStream(out, new CRC32());
zipOut = new ZipOutputStream(cos);
zipOut.putNextEntry(e);
}
@Override
public void write(int b) throws IOException {
zipOut.write(b);
}
@Override
public void close() throws IOException {
zipOut.close();
}
@Override
public void flush() throws IOException {
zipOut.flush();
}
/**
* 测试用例
*/
public static void main(String[] args) throws IOException{
FileOutputStream fos = new FileOutputStream("d:/tmp/100.zip");//最终生成的文件
ZipFileCompressOutputStream out = new ZipFileCompressOutputStream("100.txt", fos);//压缩包中的文件名
out.write("哇嘎嘎ZIP".getBytes());//写入txt文件的内容。
out.close();
}
}
测试用例看不懂的同学,我简单解释一下。
如果没有我这个新建的 ZipFileCompressOutputStream 类,那么,其实是在向 FileOutputStream 当中写入数据,生成的就是文本文件了。
但是,通过将输出流 fos 包装后,原有要写入的数据的操作没有变化,但是,输出流输出的就变成ZIP压缩流了,所以,生成的文件名也相应的变成zip文件名了。
压缩包中的文件名,包装fos的时候,当做参数传递进去了。