Java zip压缩

来源:互联网 发布:传奇网络加速器免费版 编辑:程序博客网 时间:2024/06/03 23:14

Java中有与zip相关的api,位于java.util.zip.*包下。
在一些应用场景中,可能需要对程序生成的文件如导出比较大的excel文件,然后需要对其压缩上传。
《Java 核心技术 卷二 高级特性》这本书中就有关于zip的介绍,下面将其摘录如下:

1.读取zip文件

zip文档通常以压缩格式存储了一个或多个文件,每个zip文档都有一个包含诸如文件名字和所使用的压缩方法等信息的头。在Java中,可以使用ZipInputStream来读入zip文档。
你可能需要浏览文档中每个单独的项,getNextEntry方法就可以返回一个描述这些项的ZipEntry类型的对象。ZipInputStream的read方法被修改为在碰到当前项的结尾时返回-1(而不是碰到zip文件的末尾),然后你必须调用closeEntry来读入下一项。下面是典型的通读zip文件的伪代码:

ZipInputStream zin = new ZipInputStream(new FileInputStream(zipname));ZipEntry entry;while((entry=zin.getNextEntry())!=null){    analyze entry;    read the contents of zin;    zin.closeEntry();}zin.close();

当希望读入某个zip项的内容时,我们可能并不想使用原生的read方法,通常,我们将使用某个更能胜任的流过滤器的方法。例如,为了读入zip文件内部的一个文本文件,我们可以使用下面的循环:

Scanner in = new Scanner(zin);while(in.hasNextLine())    do something with in.nextLine();

注意: zip输入流在读入zip文件发生错误时,会抛出ZipException。通常这种错误在zip文件被破坏时发生。

2.写出到zip文件

要写出到zip文件,可以使用ZipOutputStream,而对于你希望放入到zip文件中的每一项,都应该创建一个ZipEntry对象,并将文件名传递给ZipEntry的构造器,它将设置其他诸如文件日期和解压缩方法等参数。如果需要,你可以覆盖这些设置。然后,你需要调用ZipOutputStream的putNextEntry方法来开始写出新文件,并将文件数据发送到zip流中。当完成时,需要调用closeEntry。然后,你需要对所有你希望存储的文件都重复这个过程。下面是代码框架:

FileOutputStream fout = new FileOutputStream("test.zip");ZipOutputStream zout = new ZipOutputStream(fout);for all files{    ZipEntry ze = new ZipEntry(filename);//  file.getName();    zout.putNextEntry(ze);    send data to zout;    zout.closeEntry();}zout.close();

注意: ZipEntry ze = new ZipEntry(filename);中的filename,这个路径是相对路径(相对于test.zip这个zip文件的路径),所以如果是目录层级的话,需要加上层级目录。

上面这段伪代码非常重要,可以帮助你很好的理解下面的递归结构程序。

package test;import java.io.BufferedInputStream;import java.io.File;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;import java.util.zip.ZipEntry;import java.util.zip.ZipOutputStream;public class ZipUtils {    public static final String EXT = ".zip";      // 符号"/"用来作为目录标识判断符      private static final String PATH = "/";      private static final int BUFFER = 1024;      /**     * 压缩文件或文件夹     * @param zipOutfile zip输出文件     * @param file 待压缩的文件或文件夹     * @throws IOException     */    public static void compressFile(File zipOutfile,File file) throws IOException{        System.out.println("Begin Compress file ...");        String zipname = zipOutfile.getName();        File outfile = new File(zipOutfile.getParent(),zipname.substring(0, zipname.lastIndexOf("."))+EXT);        if(outfile.exists()) return;        ZipOutputStream zout = new ZipOutputStream(new FileOutputStream(outfile));        putEntry(zout,file,PATH);        zout.close();        System.out.println("END");    }    /**     * 递归地将 文件或目录 放置到输出流中      * @param zout     * @param file      * @param curdir 当前目录层级     * @throws IOException     */    private static void putEntry(ZipOutputStream zout,File file,String curdir) throws IOException{        if(file.isFile()){            ZipEntry ze = new ZipEntry(curdir+file.getName());            zout.putNextEntry(ze);            BufferedInputStream bis = new BufferedInputStream(new FileInputStream(                      file));              byte[] b = new byte[BUFFER];            int count ;            while((count=bis.read(b, 0, BUFFER))!=-1)                zout.write(b, 0, count);            bis.close();            zout.closeEntry();        }else{            ZipEntry ze = new ZipEntry(curdir+file.getName()+PATH);//放置目录到zout  带 / 表示目录            zout.putNextEntry(ze);            zout.closeEntry();            for(File f : file.listFiles())                 putEntry(zout,f,curdir+file.getName()+PATH);        }    }    /**     * 压缩文件或目录 实际调用的是compressFile(ZipOutputStream,File)     * @param file 文件或目录     * @throws IOException     */    public static void compressFile(File file)throws IOException{        System.out.println("Begin Compress single file or dir...");        String zipname = file.getName();        System.out.println(file.getName()+","+file.getParent()+","+file.getPath());        if(file.isFile()){            File zipOutfile = new File(file.getParent(),zipname.substring(0, zipname.lastIndexOf("."))+EXT);            compressFile(zipOutfile,file);        }else{            File zipOutfile = new File(file.getParent(),zipname+EXT);            compressFile(zipOutfile,file);        }    }    public static void main(String[] args) throws Exception {        //File file = new File("E:\\CSV\\f.txt");        File file = new File("E:/CSV/fd");        compressFile(file);    }}

在压缩某个文件夹时,比较费解的是如何将该文件夹的文件都放置在一个zip中,并且文件的层级关系保持不变,所以上面递归的核心地方是当子文件是文件夹时,需要递归地将该子文件夹中的文件entry放置到该文件夹下,所以参数需要传递一个表示当前层级的curdir。

0 0
原创粉丝点击