java生成zip压缩文件

jdk自身有zip相关的代码,不过直到1.6的版本没有提供设置字符集的接口,因此都会出现中文乱码,目前网上的方案大多需要引入ant包进行处理:

//创建org.apache.tools.zip.ZipOutputStream
ZipOutputStream zos = new ZipOutputStream(cos);
zos.setEncoding("gbk");


然而,1.7已经修复了这个问题

在jdk7中的java.util.zip.ZipOutputStream新增了这样一个构造方法:
    /**
     * Creates a new ZIP output stream.
     *
     * @param out the actual output stream
     *
     * @param charset the {@linkplain java.nio.charset.Charset charset}
     *                to be used to encode the entry names and comments
     *
     * @since 1.7
     */
    public ZipOutputStream(OutputStream out, Charset charset) {
        super(out, new Deflater(Deflater.DEFAULT_COMPRESSION, true));
        if (charset == null)
            throw new NullPointerException("charset is null");
        this.zc = ZipCoder.get(charset);
        usesDefaultDeflater = true;
    }

这就为我们设置字符集提供了接口

ZipOutputStream zos = new ZipOutputStream(cos, Charset.forName("gbk"));


这样一来两个方法基本来说可以算是等效了,后面的新增文件方法都相同的
给一个使用jdk自带ZipOutputStream的直接取得zip文件字节数组的方案


import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.RandomStringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.nio.charset.Charset;
import java.util.HashSet;
import java.util.Set;
import java.util.zip.CRC32;
import java.util.zip.CheckedOutputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * Created with IntelliJ IDEA.
 * User: yixian
 * Date: 13-10-17
 * Time: 下午2:52
 * 将文件夹压缩并取回zip文件byte[]
 */
public class DefaultZipper implements IZipper {
    private Set<String> filePathSet = new HashSet<String>();
    private File targetFile;
    private Logger logger = LoggerFactory.getLogger(getClass());

    public DefaultZipper() {
        String tempDirectory = FileUtils.getTempDirectoryPath();
        if (!tempDirectory.endsWith(File.separator)) {
            tempDirectory += File.separator;
        }
        targetFile = initRandomTarget(tempDirectory);
    }

    private synchronized File initRandomTarget(String tempDirectory) {
        File target;
        do {
            String fileName = RandomStringUtils.random(20, true, true);
            String targetFilePath = tempDirectory + fileName;
            target = new File(targetFilePath);
        } while (target.exists());
        return target;
    }

    private boolean checkFilePath(String path) {
        File file = new File(path);
        return file.exists();
    }

    @Override
    public boolean addFile(String filePath) {
        if (checkFilePath(filePath)) {
            filePathSet.add(filePath);
            return true;
        }
        return false;
    }

    @Override
    public String[] addFiles(String... paths) {
        String[] notExistsFiles = new String[0];
        for (String path : paths) {
            if (!addFile(path)) {
                ArrayUtils.add(notExistsFiles, path);
            }
        }
        return notExistsFiles;
    }

    @Override
    public byte[] doCompress() throws IOException {
        FileOutputStream fos = new FileOutputStream(targetFile);
        CheckedOutputStream cos = new CheckedOutputStream(fos, new CRC32());
        ZipOutputStream zos = new ZipOutputStream(cos, Charset.forName("gbk"));
        String baseDir = "";
        for (String filePath : filePathSet) {
            compress(new File(filePath), zos, baseDir);
        }
        zos.close();
        return loadTargetFileBytes();
    }

    private void compress(File file, ZipOutputStream zos, String basePath) {
        if (file.isDirectory()) {
            logger.debug("compressing dir:" + basePath + file.getName());
            compressDirectory(file, zos, basePath);
        } else {
            logger.debug("compressing file:" + basePath + file.getName());
            compressFile(file, zos, basePath);
        }
    }

    private void compressDirectory(File dir, ZipOutputStream zos, String basePath) {
        File[] childrenFiles = dir.listFiles();
        for (File child : childrenFiles != null ? childrenFiles : new File[0]) {
            compress(child, zos, basePath + dir.getName() + "/");
        }
    }

    private void compressFile(File file, ZipOutputStream zos, String basePath) {
        if (!file.exists()) {
            return;
        }
        try {
            BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
            String entryName = basePath + file.getName();
            ZipEntry entry = new ZipEntry(entryName);
            zos.putNextEntry(entry);
            byte[] buffer = FileUtils.readFileToByteArray(file);
            zos.write(buffer);
            zos.flush();
            zos.closeEntry();
            bis.close();
        } catch (IOException ignored) {
        }
    }

    private byte[] loadTargetFileBytes() {
        try {
            byte[] fileBytes = FileUtils.readFileToByteArray(targetFile);
            boolean deleted = targetFile.delete();
            logger.debug("file:" + targetFile.getAbsoluteFile() + " deleted:" + deleted);
            return fileBytes;
        } catch (IOException e) {
            return new byte[0];
        }
    }
}



引入了两个commons包,给出Maven Dependency
        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.4</version>
        </dependency>
        <dependency>
            <groupId>commons-lang</groupId>
            <artifactId>commons-lang</artifactId>
            <version>2.6</version>
        </dependency>


测试:
import com.skytech.crius.city.util.DefaultZipper;
import org.junit.Test;

import java.io.FileOutputStream;
import java.io.IOException;

/**
 * Created with IntelliJ IDEA.
 * User: yixian
 * Date: 13-10-21
 * Time: 上午10:30
 */
public class ZipTest {
    private static final String SOURCE_FILE_PATH = "d:\\foo\\bar";
    @Test
    public void DefaultZipperTest() throws IOException {
        IZipper zipper = new DefaultZipper();
        zipper.addFile(SOURCE_FILE_PATH);
        byte[] bytes = zipper.doCompress();
        FileOutputStream fos = new FileOutputStream("d:\\test.zip");
        fos.write(bytes);
        fos.flush();
        fos.close();
    }
}


注意这个案例因为要把zip压缩文件整体读入内存所以如果压的文件体积太大就会......

你可能感兴趣的:(java,zip)