JAVA中文件压缩、解压小方法分享

来源:互联网 发布:照片转卡通软件 编辑:程序博客网 时间:2024/05/16 12:16

      最近项目中有一个功能需要将文件压缩和解压,我这边最开始使用的是JDK中的类库,在网上找了一些样例,或多或少总是存在一些BUG,而且中文路径乱码的问题始终不能解决。没办法最终只有换方案,最后使用了apache-ant中的工具类来实现的,并且测试通过。源码也是从网上找到的,做了少量修改,这里给大家分享一下。


package com.aeai.zip;

 

import java.io.BufferedInputStream;

import java.io.BufferedOutputStream;

import java.io.File;

import java.io.FileInputStream;

import java.io.FileNotFoundException;

import java.io.FileOutputStream;

import java.io.IOException;

import java.util.Enumeration;

import java.util.zip.CRC32;

import java.util.zip.CheckedOutputStream;

import java.util.zip.Deflater;

import java.util.zip.ZipException;

import org.apache.tools.zip.ZipEntry;

import org.apache.tools.zip.ZipFile;

import org.apache.tools.zip.ZipOutputStream;

 

/**

 * 利用apache提供的ant.jar,提供对单个文件与目录的压缩,并支持是否需要创建压缩源目录、中文路径

 *

 * @Title

 * @DescriptionZipCompress

 * @Version 1.2

 */

public class ZipCompress {

 

    private static boolean isCreateSrcDir=true;//是否创建源目录

 

    /**

     * 对文件夹或者文件进行压缩

     *

     * @Time 2012-3-9上午09:32:35 create

     * @param src

     *      文件路径(全)

     * @param archive

     *      压缩路径(全)

     * @param comment

     *      压缩包注释

     * @throws FileNotFoundException

     * @throws IOException

     */

    public static void writeByApacheZipOutputStream(Stringsrc, String archive,

            String comment) throws FileNotFoundException,IOException {

        // ----压缩文件:

        FileOutputStream f = newFileOutputStream(archive);

        // 使用指定校验和创建输出流

        CheckedOutputStream csum = new CheckedOutputStream(f,new CRC32());

 

        ZipOutputStream zos = new ZipOutputStream(csum);

        // 支持中文

        zos.setEncoding("GBK");

        BufferedOutputStream out = newBufferedOutputStream(zos);

        // 设置压缩包注释

        zos.setComment(comment);

        // 启用压缩

        zos.setMethod(ZipOutputStream.DEFLATED);

        // 压缩级别为最强压缩,但时间要花得多一点

        zos.setLevel(Deflater.BEST_COMPRESSION);

 

        File srcFile = new File(src);

 

        if (!srcFile.exists()

                || (srcFile.isDirectory()&& srcFile.list().length == 0)) {

            throw new FileNotFoundException(

                    "File must exist and  ZIP filemust have at least one entry.");

        }

        // 获取压缩源所在父目录

        src = src.replaceAll("\\\\","/");

        String prefixDir = null;

        if (srcFile.isFile()) {

            prefixDir = src.substring(0,src.lastIndexOf("/") + 1);

        } else {

            prefixDir = (src.replaceAll("/$","") + "/");

        }

 

        // 如果不是根目录

        if (prefixDir.indexOf("/") != (prefixDir.length() - 1)

                && isCreateSrcDir){

            prefixDir = prefixDir.replaceAll("[^/]+/$","");

        }

 

        // 开始压缩

        writeRecursive(zos, out, srcFile,prefixDir);

 

        out.close();

        // 注:校验和要在流关闭后才准备,一定要放在流被关闭后使用

        System.out.println("Checksum: " +csum.getChecksum().getValue());

    }

 

    /**

     * 使用 org.apache.tools.zip.ZipFile解压文件,它与 java类库中的 java.util.zip.ZipFile

     * 使用方式是一新的,只不过多了设置编码方式的接口。

     *

     * 注,apache没有提供 ZipInputStream类,所以只能使用它提供的ZipFile来读取压缩文件。

     *

     * @param archive

     *           压缩包路径

     *           解压路径

     * @throws IOException

     * @throws FileNotFoundException

     * @throws ZipException

     */

    public static void readByApacheZipFile(Stringarchive, String decompressDir)

            throws IOException, FileNotFoundException,ZipException {

        BufferedInputStream bi;

 

        ZipFile zf = new ZipFile(archive,"GBK");// 支持中文

 

        Enumeration<?> e =zf.getEntries();

        while (e.hasMoreElements()) {

            ZipEntry ze2 = (ZipEntry)e.nextElement();

            String entryName = ze2.getName();

            String path = decompressDir + "/" + entryName;

            if (ze2.isDirectory()) {

                System.out.println("正在创建解压目录 - " + entryName);

                File decompressDirFile = new File(path);

                if (!decompressDirFile.exists()) {

                    decompressDirFile.mkdirs();

                }

            } else {

                System.out.println("正在创建解压文件 - " + entryName);

                String fileDir =path.substring(0, path.lastIndexOf("/"));

                File fileDirFile = new File(fileDir);

                if (!fileDirFile.exists()) {

                    fileDirFile.mkdirs();

                }

                BufferedOutputStream bos = new BufferedOutputStream(

                        newFileOutputStream(decompressDir +"/" + entryName));

 

                bi = new BufferedInputStream(zf.getInputStream(ze2));

                byte[] readContent =new byte[1024];

                int readCount = bi.read(readContent);

                while (readCount != -1) {

                    bos.write(readContent, 0,readCount);

                    readCount =bi.read(readContent);

                }

                bos.close();

            }

        }

        zf.close();

    }

 

    /**

     * 递归压缩

     *

     * 使用 org.apache.tools.zip.ZipOutputStream类进行压缩,它的好处就是支持中文路径,Java类库中的

     * java.util.zip.ZipOutputStream 压缩中文文件名时压缩包会出现乱码。使用apache 中的这个类与 java

     * 类库中的用法是一新的,只是能设置编码方式了。

     *

     * @param zos

     * @param bo

     * @param srcFile

     * @param prefixDir

     * @throws IOException

     * @throws FileNotFoundException

     */

    private static voidwriteRecursive(ZipOutputStream zos,

            BufferedOutputStream bo, FilesrcFile, String prefixDir)

            throws IOException, FileNotFoundException {

        ZipEntry zipEntry;

 

        String filePath =srcFile.getAbsolutePath().replaceAll("\\\\","/")

                .replaceAll("//","/");

        if (srcFile.isDirectory()) {

            filePath = filePath.replaceAll("/$","") + "/";

        }

        String entryName =filePath.replace(prefixDir, "").replaceAll("/$", "");

        if (srcFile.isDirectory()) {

            if (!"".equals(entryName)) {

                System.out.println("正在创建目录 - " + srcFile.getAbsolutePath()

                        + " entryName=" + entryName);

 

                // 如果是目录,则需要在写目录后面加上 /

                zipEntry = new ZipEntry(entryName +"/");

                zos.putNextEntry(zipEntry);

            }

 

            File srcFiles[] =srcFile.listFiles();

            for (int i = 0; i < srcFiles.length; i++) {

                writeRecursive(zos, bo,srcFiles[i], prefixDir);

            }

        } else {

            System.out.println("正在写文件 - " + srcFile.getAbsolutePath()

                    +" entryName=" + entryName);

            BufferedInputStream bi = new BufferedInputStream(

                    new FileInputStream(srcFile));

 

            // 开始写入新的ZIP文件条目并将流定位到条目数据的开始处

            zipEntry = new ZipEntry(entryName);

            zos.putNextEntry(zipEntry);

            byte[] buffer =new byte[1024];

            int readCount = bi.read(buffer);

 

            while (readCount != -1) {

                bo.write(buffer, 0, readCount);

                readCount = bi.read(buffer);

            }

            // 注,在使用缓冲流写压缩文件时,一个条件完后一定要刷新一把,不

            // 然可能有的内容就会存入到后面条目中去了

            bo.flush();

            // 文件读完后关闭

            bi.close();

        }

    }

   

    /**

     * @param args

     * @throws IOException

     */

    public static void main(String[] args)throws IOException {

        //writeByApacheZipOutputStream("D:/data2", "D:/data2.zip","");

        readByApacheZipFile("D:/data2.zip","D:/data3");

    }

}



0 0
原创粉丝点击