package shop.alien.util.compress;

import java.io.*;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * 压缩文件工具类
 *
 * @author ssk
 */
public class CompressUtil {

    /**
     * 定义压缩类型
     */
    private static final String TYPE_ZIP = ".zip";
    private static final String TYPE_7Z = ".7z";
    private static final String TYPE_RAR = ".rar";

    public static void main(String[] args) {
        String srcFilePath = "D:\\MyTest\\new";
        //使用时间命名zip文件,文件名内不能有特殊符号
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddhhmmss");
        String newFileName = sdf.format(new Date());
        String destFilePath = "D:\\MyTest\\" + newFileName + TYPE_ZIP;
        //第一个参数是需要压缩的源路径；第二个参数是压缩文件的目的路径，这边需要将压缩的文件名字加上去
        compress(srcFilePath, destFilePath);
    }

    /**
     * 压缩文件
     *
     * @param srcFilePath  压缩源路径
     * @param destFilePath 压缩目的路径
     */
    public static void compress(String srcFilePath, String destFilePath) {
        destFilePath = destFilePath + TYPE_ZIP;
        File src = new File(srcFilePath);
        if (!src.exists()) {
            throw new RuntimeException(srcFilePath + "不存在");
        }
        File zipFile = new File(destFilePath);
        try {
            FileOutputStream fos = new FileOutputStream(zipFile);
            ZipOutputStream zos = new ZipOutputStream(fos);
            String baseDir = "";
            compressByType(src, zos, baseDir);
            zos.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 按照原路径的类型就行压缩。文件路径直接把文件压缩
     *
     * @param file    压缩源路径
     * @param zos     压缩转换中文件
     * @param baseDir 转换成所有系统都可以识别的路径
     */
    private static void compressByType(File file, ZipOutputStream zos, String baseDir) {
        if (!file.exists()) {
            return;
        }
        System.out.println("压缩路径" + baseDir + file.getName());
        //判断文件是否是文件，如果是文件调用compressFile方法,如果是路径，则调用compressDir方法；
        if (file.isFile()) {
            compressFile(file, zos, baseDir);
        } else if (file.isDirectory()) {
            compressDir(file, zos, baseDir);
        }
    }

    /**
     * 压缩文件
     *
     * @param file    压缩源路径
     * @param zos     压缩转换中文件
     * @param baseDir 转换成所有系统都可以识别的路径
     */
    private static void compressFile(File file, ZipOutputStream zos, String baseDir) {
        if (!file.exists()) {
            return;
        }
        try {
            BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
            ZipEntry entry = new ZipEntry(baseDir + file.getName());
            zos.putNextEntry(entry);
            int count;
            byte[] buf = new byte[1024];
            while ((count = bis.read(buf)) != -1) {
                zos.write(buf, 0, count);
            }
            bis.close();
        } catch (Exception e) {
            System.err.println("ZipUtil:压缩文件失败");
        }
    }

    /**
     * 压缩文件夹
     *
     * @param dir     压缩源路径
     * @param zos     压缩转换中文件
     * @param baseDir 转换成所有系统都可以识别的路径
     */
    private static void compressDir(File dir, ZipOutputStream zos, String baseDir) {
        if (!dir.exists()) {
            return;
        }
        File[] files = dir.listFiles();
        assert files != null;
        if (files.length == 0) {
            try {
                zos.putNextEntry(new ZipEntry(baseDir + dir.getName() + File.separator));
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        for (File file : files) {
            compressByType(file, zos, baseDir + dir.getName() + File.separator);
        }
    }
}