使用Java压缩文件生成各种zip包总结(整理为工具类版)

最近由于客户来回修改需求,使得我对代码也是反复修改,最终折腾完毕后,让我总结了3种Java生成的zip包。

1.普通zip包,解压后的样子与打包压缩前一模一样,直接解压即可。

过程如下:

打包E盘下packs文件夹中的内容,生成的zip包输出到E盘下,名称为packs.zip

具体代码实现过程注释即可。

import java.nio.file.Paths;


//compress方法需要传入2个参数,是两个地址
//第一个地址是目标打包文件的地址,第二个是zip包输出的地址
public static void main(String[] args) throws IOException {
        String hallFilePath = "E:/" +  "packs";
        compress(Paths.get(hallFilePath).toString(), hallFilePath + ".zip");
    }

//由此开始是所有相关的工具方法
public static void compress(String fromPath, String toPath) throws IOException {
        File fromFile = new File(fromPath);
        File toFile = new File(toPath);
        if (!fromFile.exists()) {
            throw new ServiceException(fromPath + "不存在!");
        }
        try (FileOutputStream outputStream = new FileOutputStream(toFile); CheckedOutputStream checkedOutputStream = new CheckedOutputStream(outputStream, new CRC32()); ZipOutputStream zipOutputStream = new ZipOutputStream(checkedOutputStream)) {
            String baseDir = "";
            compress(fromFile, zipOutputStream, baseDir);
        }
    }

    private static void compress(File file, ZipOutputStream zipOut, String baseDir) throws IOException {
        if (file.isDirectory()) {
            compressDirectory(file, zipOut, baseDir);
        } else {
            compressFile(file, zipOut, baseDir);
        }
    }

    private static void compressFile(File file, ZipOutputStream zipOut, String baseDir) throws IOException {
        if (!file.exists()) {
            return;
        }
        try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file))) {
            ZipEntry entry = new ZipEntry(baseDir + file.getName());
            zipOut.putNextEntry(entry);
            int count;
            byte[] data = new byte[BUFFER];
            while ((count = bis.read(data, 0, BUFFER)) != -1) {
                zipOut.write(data, 0, count);
            }
        }
    }

    private static void compressDirectory(File dir, ZipOutputStream zipOut, String baseDir) throws IOException {
        File[] files = dir.listFiles();
        if (files != null && ArrayUtils.isNotEmpty(files)) {
            for (File file : files) {
                compress(file, zipOut, baseDir + dir.getName() + File.separator);
            }
        }
    }

压缩前的目标文件如下:

使用Java压缩文件生成各种zip包总结(整理为工具类版)_第1张图片

 压缩后输出的文件以及解压后:

使用Java压缩文件生成各种zip包总结(整理为工具类版)_第2张图片使用Java压缩文件生成各种zip包总结(整理为工具类版)_第3张图片

2.压缩后的压缩包解压即是文件,不需要文件夹,就是上面的案例,解压后还有一个packs文件夹,这里跳过,解压出来就是文件列表:

大体步骤相似,打包时代码需要调整,先上全部的代码:

public static void main(String[] args) throws IOException {
        String hallFilePath = "E:/" +  "packs";
        compress(Paths.get(hallFilePath).toString(), hallFilePath + ".zip");
    }

public static void compress(String fromPath, String toPath) throws IOException {
        File fromFile = new File(fromPath);
        File toFile = new File(toPath);
        if (!fromFile.exists()) {
            throw new ServiceException(fromPath + "不存在!");
        }
        try (FileOutputStream outputStream = new FileOutputStream(toFile); CheckedOutputStream checkedOutputStream = new CheckedOutputStream(outputStream, new CRC32()); ZipOutputStream zipOutputStream = new ZipOutputStream(checkedOutputStream)) {
            String baseDir = "";
            compress(fromFile, zipOutputStream, baseDir);
        }
    }

    private static void compress(File file, ZipOutputStream zipOut, String baseDir) throws IOException {
        if (file.isDirectory()) {
            compressDirectory(file, zipOut, baseDir);
        } else {
            if (baseDir.equals("packs" + File.separator)) {
                baseDir = File.separator;
            } else if (baseDir.equals("packs" + File.separator + "examineeInfo" + File.separator)) {
                baseDir = "examineeInfo" + File.separator;
            }
            compressFile(file, zipOut, baseDir);
        }
    }

    private static void compressFile(File file, ZipOutputStream zipOut, String baseDir) throws IOException {
        if (!file.exists()) {
            return;
        }
        try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file))) {
            ZipEntry entry = new ZipEntry(baseDir + file.getName());
            zipOut.putNextEntry(entry);
            int count;
            byte[] data = new byte[BUFFER];
            while ((count = bis.read(data, 0, BUFFER)) != -1) {
                zipOut.write(data, 0, count);
            }
        }
    }

    private static void compressDirectory(File dir, ZipOutputStream zipOut, String baseDir) throws IOException {
        File[] files = dir.listFiles();
        if (files != null && ArrayUtils.isNotEmpty(files)) {
            for (File file : files) {
                compress(file, zipOut, baseDir + dir.getName() + File.separator);
            }
        }
    }

这里主要是有第二个compress方法来处理:

由于文件夹结构如下:

使用Java压缩文件生成各种zip包总结(整理为工具类版)_第4张图片

 这个方法在打包时,将外层的文件夹去掉,只保留内部文件夹

private static void compress(File file, ZipOutputStream zipOut, String baseDir) throws IOException {
        if (file.isDirectory()) {
            compressDirectory(file, zipOut, baseDir);
        } else {
            //如果是文件夹,进来判断,是最外层packs文件夹还是内部的examineeInfo文件夹
            //是最外层的则忽略掉,是内部的则把外层文件夹名称去掉
            if (baseDir.equals("packs" + File.separator)) {
                baseDir = File.separator;
            } else if (baseDir.equals("packs" + File.separator + "examineeInfo" + File.separator)) {
                baseDir = "examineeInfo" + File.separator;
            }
            compressFile(file, zipOut, baseDir);
        }
    }

这样压缩后的zip包解压后,直接出现文件,没有最外层文件夹:

使用Java压缩文件生成各种zip包总结(整理为工具类版)_第5张图片

3.压缩时给zip包添加密码:

打出一个带解压密码的zip包:

程序运行示例截图: 

使用Java压缩文件生成各种zip包总结(整理为工具类版)_第6张图片

示例代码:

public static void main(String[] args) {
        //随机密码生成工具
        String ownerPassword = PdfEncryptUtil.getCharAndNum(20);
        //打包目标文件夹
        String hallFilePath = "E:" + File.separator+ "packs";
        //压缩包输出文件夹
        String outPath = "E:" +File.separator+ "examineeInfo.zip";
       //调用压缩方法zip进行压缩,参数含义下面介绍,返回的是压缩包的输出路径
        String zipPath = zip(hallFilePath, outPath, false, "ceshi");
        //打印出来 
        System.out.println(zipPath);
    }

zip方法工具中的方法:

/**
     * 使用给定密码压缩指定文件或文件夹到指定位置.
     * 

* dest可传最终压缩文件存放的绝对路径,也可以传存放目录,也可以传null或者"" * 如果传null或者""则将压缩文件存放在当前目录,即跟源文件同目录,压缩文件名取源文件名,以.zip为后缀; * 如果以路径分隔符(File.separator)结尾,则视为目录,压缩文件名取源文件名,以.zip为后缀,否则视为文件名. * * @param src 要压缩的文件或文件夹路径 * @param dest 压缩文件存放路径 * @param isCreateDir 是否在压缩文件里创建目录,仅在压缩文件为目录时有效. * 如果为false,将直接压缩目录下文件到压缩文件. * @param passwd 压缩使用的密码 * @return 最终的压缩文件存放的绝对路径, 如果为null则说明压缩失败. */ public static String zip(String src, String dest, boolean isCreateDir, String passwd) { File srcFile = new File(src); dest = buildDestinationZipFilePath(srcFile, dest); ZipParameters parameters = new ZipParameters(); // 压缩方式 parameters.setCompressionMethod(Zip4jConstants.COMP_DEFLATE); // 压缩级别 parameters.setCompressionLevel(Zip4jConstants.DEFLATE_LEVEL_NORMAL); if (!StringUtils.isEmpty(passwd)) { parameters.setEncryptFiles(true); // 加密方式 parameters.setEncryptionMethod(Zip4jConstants.ENC_METHOD_STANDARD); parameters.setPassword(passwd.toCharArray()); } try { ZipFile zipFile = new ZipFile(dest); if (srcFile.isDirectory()) { // 如果不创建目录的话,将直接把给定目录下的文件压缩到压缩文件,即没有目录结构 if (!isCreateDir) { File[] subFiles = srcFile.listFiles(); for (int i = 0; i < subFiles.length; i++) { if (subFiles[i].isDirectory()) { zipFile.addFolder(subFiles[i], parameters); } else { ArrayList temp = new ArrayList(); Collections.addAll(temp, subFiles[i]); zipFile.addFiles(temp, parameters); } } return dest; } zipFile.addFolder(srcFile, parameters); } else { zipFile.addFile(srcFile, parameters); } return dest; } catch (ZipException e) { e.printStackTrace(); } return null; } private static String buildDestinationZipFilePath(File srcFile, String destParam) { if (StringUtils.isEmpty(destParam)) { if (srcFile.isDirectory()) { destParam = srcFile.getParent() + File.separator + srcFile.getName() + ".zip"; } else { String fileName = srcFile.getName().substring(0, srcFile.getName().lastIndexOf(".")); destParam = srcFile.getParent() + File.separator + fileName + ".zip"; } } else { // 在指定路径不存在的情况下将其创建出来 createDestDirectoryIfNecessary(destParam); if (destParam.endsWith(File.separator)) { String fileName = ""; if (srcFile.isDirectory()) { fileName = srcFile.getName(); } else { fileName = srcFile.getName().substring(0, srcFile.getName().lastIndexOf(".")); } destParam += fileName + ".zip"; } } return destParam; } private static void createDestDirectoryIfNecessary(String destParam) { File destDir = null; if (destParam.endsWith(File.separator)) { destDir = new File(destParam); } else { destDir = new File(destParam.substring(0, destParam.lastIndexOf(File.separator))); } if (!destDir.exists()) { destDir.mkdirs(); } }

这里打包出来的加密zip包也是解压开就是文件列表的格式,没有最外层文件夹包裹,如果想要最外层文件夹包裹,只需要改动下zip方法的try块中的if...else语句即可:

try {
            ZipFile zipFile = new ZipFile(dest);
            if (srcFile.isDirectory()) {
                // 如果不创建目录的话,将直接把给定目录下的文件压缩到压缩文件,即没有目录结构
                if (!isCreateDir) {
                    File[] subFiles = srcFile.listFiles();
                    ArrayList temp = new ArrayList();
                    Collections.addAll(temp, subFiles);
                    zipFile.addFiles(temp, parameters);
                    return dest;
                }
                zipFile.addFolder(srcFile, parameters);
            } else {
                zipFile.addFile(srcFile, parameters);
            }
            return dest;
        } catch (ZipException e) {
            e.printStackTrace();
        }

生成效果:

使用Java压缩文件生成各种zip包总结(整理为工具类版)_第7张图片

使用Java压缩文件生成各种zip包总结(整理为工具类版)_第8张图片

注意:

1.zip包输出地址在定义时,一定要以.zip结尾,否则会出错。

2.代表文件夹层级关系的/在有的方法中,或者linux服务器上不识别,最好使用File.separator来表示层级,上面我也有用到过。

3.密码最好使用动态生成的密码,来提高安全性。

压缩的方法很多,工作之余匆匆记录,肯定有不是很合理很全面的地方,有大佬看到欢迎指点。

你可能感兴趣的:(Java日常,java,开发语言)