文件压缩工具类

解决了中文乱码问题

导入apache的jar包

<dependency>
    <groupId>org.apache.ant</groupId>
    <artifactId>ant</artifactId>
    <version>1.10.5</version>
</dependency>

代码如下

package com.dist.util;

import com.google.common.collect.Lists;
import org.apache.commons.lang3.StringUtils;
import org.apache.tools.zip.ZipEntry;
import org.apache.tools.zip.ZipOutputStream;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Function;
import java.util.zip.CRC32;
import java.util.zip.CheckedOutputStream;

/**
 * 压缩文件 无中文乱码问题
 * @author qyp
 * 2018-3-24 下午05:12:30
 */
public class ZipUtils {

    private final static Logger logger = LoggerFactory.getLogger(ZipUtils.class);

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

        File rootFile = new File("E:\temp\test");

        List<InputStream> ins = new ArrayList<>();
        List<String> names = new ArrayList<>();
        List<String> namePaths = Lists.newArrayList();
        File[] list = rootFile.listFiles();
        for (File f : list) {
            names.add(f.getName());
            namePaths.add(f.getAbsolutePath());
            ins.add(new FileInputStream(f));
        }
        //zipByInStream("e:\temp\a.zip", ins, names);
        //zipByFileNames("e:\temp\a.zip", namePaths);
        zipByFiles("e:\temp\a.zip", Arrays.asList(list));
	}

    /**
     * 将文件的流集合代表的文件压缩成一个压缩包并保存到指定位置
     * @param savePath  生成的压缩包的位置
     * @param inputStreams 文件流集合
     * @param names     文件名称集合
     * @throws Exception 如果文件路径不存在或者压缩失败,那么久会抛异常
     */
	public static void zipByInStream(String savePath, List<InputStream> inputStreams, List<String> names) throws Exception {
        ZipOutputStream zos = getOutPutStream(savePath);
        BufferedReader bufr = null;
		// 缓存输出流
        try (BufferedOutputStream out = new BufferedOutputStream(zos)) {
            for (int i = 0, len = inputStreams.size(); i < len; i++) {
                //添加一个条目到压缩包
                zos.putNextEntry(new ZipEntry(names.get(i)));
                int c;
                // StandardCharsets.ISO_8859_1 防止文件内容乱码
                bufr = new BufferedReader(new InputStreamReader(inputStreams.get(i), StandardCharsets.ISO_8859_1));
                while ((c = bufr.read()) != -1) {
                    out.write(c);
                }
                out.flush();
                if (bufr != null) {
                    bufr.close();
                }
            }
        } catch (IOException r) {
            throw new RuntimeException("文件压缩失败");
        } finally {
            if (bufr != null) {
                bufr.close();
            }
        }
	}

    /**
     * 根据文件名集合获取文件并压缩
     * @param savePath          保存的压缩文件路径
     * @param targetFileNames   被压缩的文件名集合(全路径)
     * @throws Exception
     */
    public static void zipByFileNames(String savePath, List<String> targetFileNames) throws Exception {
        Function<Object, String> nameFun = (obj) -> getFileName((String) obj);
        Function<Object, InputStream> inFun = (obj) -> {
            try {
                return new FileInputStream((String) obj);
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }
            return null;
        };
        zipFile(savePath, targetFileNames, nameFun, inFun);
    }

    /**
     * 根据文件集合生成压缩文件
     * @param savePath      保存的压缩文件路径
     * @param targetFiles   被压缩的文件集合
     * @throws Exception
     */
    public static void zipByFiles(String savePath, List<File> targetFiles) throws Exception {
	    Function<Object, String> nameFun = (obj) -> ((File)obj).getName();
        Function<Object, InputStream> inFun = (obj) -> {
            try {
                return new FileInputStream((File) obj);
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }
            return null;
        };
        zipFile(savePath, targetFiles, nameFun, inFun);
    }

    /**
     * 压缩文件
     * @param savePath  保存的压缩文件路径
     * @param targets   被压缩的对象(文件名集合(全路径),或者文件集合)
     * @param nameFun   获取文件名的Function对象
     * @param inFun     获取InputStream的Function对象
     * @throws Exception
     */
    private static void zipFile(String savePath, List<?> targets, Function<Object, String> nameFun, Function<Object, InputStream> inFun) throws Exception {
        ZipOutputStream zos = getOutPutStream(savePath);
        BufferedReader bufr = null;
        // 缓存输出流
        try (BufferedOutputStream out = new BufferedOutputStream(zos)) {
            for (int i = 0, len = targets.size(); i < len; i++) {
                zos.putNextEntry(new ZipEntry(nameFun.apply(targets.get(i))));
                int c;
                bufr = new BufferedReader(new InputStreamReader(inFun.apply(targets.get(i)), StandardCharsets.ISO_8859_1));
                while ((c = bufr.read()) != -1) {
                    out.write(c);
                }
                out.flush();
                if (bufr != null) {
                    bufr.close();
                }
            }
            logger.info("成功压缩{}个文件,保存地址为【{}】", targets.size(), savePath);
        } catch (IOException r) {
            throw new RuntimeException("文件压缩失败");
        } finally {
            if (bufr != null) {
                bufr.close();
            }
        }
    }

    /**
     * 获取apache的ZipOutputStream流
     * @param savePath 保存压缩文件的路径
     * @return
     * @throws FileNotFoundException 如果保存路径不存在,那么将会抛异常
     */
    private static ZipOutputStream getOutPutStream(String savePath) throws FileNotFoundException {
        //输出的压缩原始文件流fileDir + "\" + "详情.zip"
        FileOutputStream f = new FileOutputStream(new File(savePath));
        // 计算和校验文件
        CheckedOutputStream csum = new CheckedOutputStream(f, new CRC32());
        // 输出的压缩文件流
        ZipOutputStream zos = new ZipOutputStream(csum);
        zos.setComment("dist文件压缩流");
        //设置压缩工具右边的文字编码  防止右边的说明文字乱码
        zos.setEncoding(System.getProperty("sun.jnu.encoding"));
        return zos;
    }

    /**
     * 获取文件名
     * @param filePath
     * @return
     */
    public static String getFileName(String filePath) {
        int idx = StringUtils.lastIndexOf(filePath, File.separator);
        if (idx != -1) {
            return StringUtils.substring(filePath, idx + 1);
        }
        return filePath;
    }

}

原文地址:https://www.cnblogs.com/qiaozhuangshi/p/11198157.html