Java compresses the file or folder into a zip (fix the problem of multiple files in the folder reporting Stream Closed error)

Project scene:

Java compresses the file or folder into a zip (fix the problem of multiple files in the folder reporting Stream Closed error)

Problem Description:

Recent projects need to compress multi-level folders into zips. I found several tools on the Internet, and they all reported errors, so find one of the tools in this article. After improving, it has been resolved that there are multiple files in the folder and report Stream Closed error problem.
ps: Java novice, I don't know if there is any problem with this change, I hope the great gods can help study the link to the
original tool article:

Cause Analysis:

zos.close(); is
changed to only close once in the outermost try-catch-finally call to avoid re-executing an error after the retreat is closed multiple times.
The original logic is not deleted, it is commented out instead

solution:

package utils;


import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


// 压缩zip方法
public class ZipUtil {
    private static final int BUFFER_SIZE = 2 * 1024;
    private static Logger logger = LoggerFactory.getLogger(ZipUtil.class);

    /**
     * 压缩成ZIP 方法1
     *
     * @param srcDir
     *            压缩文件夹路径
     * @param out
     *            压缩文件输出流
     * @param KeepDirStructure
     *            是否保留原来的目录结构,true:保留目录结构;
     *            false:所有文件跑到压缩包根目录下(注意:不保留目录结构可能会出现同名文件,会压缩失败)
     * @throws RuntimeException
     *             压缩失败会抛出运行时异常
     */
    public static void toZip(String srcDir, OutputStream out, boolean KeepDirStructure){
        long start = System.currentTimeMillis();
        ZipOutputStream zos = null;
        try {
            zos = new ZipOutputStream(out);
            File sourceFile = new File(srcDir);
            compress(sourceFile, zos, sourceFile.getName(), KeepDirStructure);
            long end = System.currentTimeMillis();
            logger.debug("压缩完成,耗时:" + (end - start) + " ms");
        } catch (Exception e) {
            e.printStackTrace();
            logger.error("系统异常:",e);
        } finally {
            //zos != null zos.close(); 并不是判断zos是否被关闭 而是这个对象是否创建成功
            if (zos != null) {
                try {
                    zos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                    logger.error("系统异常:",e);
                }
            }
        }
    }

    /**
     * 压缩成ZIP 方法2
     *
     * @param srcFiles
     *            需要压缩的文件列表
     * @param out
     *            压缩文件输出流
     * @throws RuntimeException
     *             压缩失败会抛出运行时异常
     */
    public static void toZip(List<File> srcFiles, OutputStream out){
        long start = System.currentTimeMillis();
        ZipOutputStream zos = null;
        try {
            zos = new ZipOutputStream(out);
            for (File srcFile : srcFiles) {
                byte[] buf = new byte[BUFFER_SIZE];
                zos.putNextEntry(new ZipEntry(srcFile.getName()));
                int len;
                FileInputStream in = new FileInputStream(srcFile);
                while ((len = in.read(buf)) != -1) {
                    zos.write(buf, 0, len);
                }
                zos.closeEntry();
                in.close();
            }
            long end = System.currentTimeMillis();
            logger.debug("压缩完成,耗时:" + (end - start) + " ms");
        } catch (Exception e) {
            e.printStackTrace();
            logger.error("系统异常:",e);
        } finally {
            if (zos != null) {
                try {
                    zos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                    logger.error("系统异常:",e);
                }
            }
        }
    }

    /**
     * 压缩成ZIP 方法2
     *
     * @param srcFiles
     *            需要压缩的文件列表
     * @param out
     *            压缩文件输出流
     * @throws RuntimeException
     *             压缩失败会抛出运行时异常
     */
    public static void toZip(File[] srcFiles, OutputStream out){
        long start = System.currentTimeMillis();
        ZipOutputStream zos = null;
        try {
            zos = new ZipOutputStream(out);
            for (File srcFile : srcFiles) {
                byte[] buf = new byte[BUFFER_SIZE];
                zos.putNextEntry(new ZipEntry(srcFile.getName()));
                int len;
                FileInputStream in = new FileInputStream(srcFile);
                while ((len = in.read(buf)) != -1) {
                    zos.write(buf, 0, len);
                }
                zos.closeEntry();
                in.close();
            }
            long end = System.currentTimeMillis();
            logger.debug("压缩完成,耗时:" + (end - start) + " ms");
        } catch (Exception e) {
            e.printStackTrace();
            logger.error("系统异常:",e);
        } finally {
            if (zos != null) {
                try {
                    zos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                    logger.error("系统异常:",e);
                }
            }
        }
    }

    /**
     *
     * 递归压缩方法
     *
     * @param sourceFile
     *            源文件
     *
     * @param zos
     *            zip输出流
     *
     * @param name
     *            压缩后的名称
     *
     * @param KeepDirStructure
     *            是否保留原来的目录结构,true:保留目录结构;
     *
     *            false:所有文件跑到压缩包根目录下(注意:不保留目录结构可能会出现同名文件,会压缩失败)
     *
     * @throws Exception
     *
     */
    //工具类有逻辑问题 已更改添加注释 便于理解
    private static void compress(File sourceFile, ZipOutputStream zos, String name,
                                 boolean KeepDirStructure) throws IOException {
        byte[] buf = new byte[BUFFER_SIZE];
        //异常改为向上层抛出 避免 zos.close(); 没有执行
//        try {
            if (sourceFile.isFile()) {
                // 向zip输出流中添加一个zip实体,构造器中name为zip实体的文件的名字
                zos.putNextEntry(new ZipEntry(name));
                // copy文件到zip输出流中
                int len;
                FileInputStream in = new FileInputStream(sourceFile);
                while ((len = in.read(buf)) != -1) {
                    zos.write(buf, 0, len);
                }
                // Complete the entry
                zos.closeEntry();
                in.close();
            } else {
                File[] listFiles = sourceFile.listFiles();
                if (listFiles == null || listFiles.length == 0) {
                    // 需要保留原来的文件结构时,需要对空文件夹进行处理
                    if (KeepDirStructure) {
                        // 空文件夹的处理
                        zos.putNextEntry(new ZipEntry(name + "/"));
                        // 没有文件,不需要文件的copy
                        zos.closeEntry();
                    }
                } else {
                    for (File file : listFiles) {
                        // 判断是否需要保留原来的文件结构
                        if (KeepDirStructure) {
                            // 注意:file.getName()前面需要带上父文件夹的名字加一斜杠,
                            // 不然最后压缩包中就不能保留原来的文件结构,即:所有文件都跑到压缩包根目录下了
                            compress(file, zos, name + "/" + file.getName(), KeepDirStructure);
                        } else {
                            compress(file, zos, file.getName(), KeepDirStructure);
                        }
                    }
                }
            }
//        }catch(Exception e){
//            e.printStackTrace();
//            logger.error("系统异常:",e);
//        } finally {
//           递归时,不需要把zip输出流关闭,zip输出流的关闭应该是在调用完递归方法后面关闭 这里不再关闭 在最外层关闭
//            if (zos != null) {
//                try {
//                    zos.close();
//                } catch (IOException e) {
//                    e.printStackTrace();
//                    logger.error("系统异常:",e);
//                }
//
//            }
//        }
    }

    public static void main(String[] args) throws Exception {
        /** 测试压缩方法1 */
		FileOutputStream fos1 = new FileOutputStream(new File("F:/11.zip"));
		ZipUtil.toZip("F:/driverDailyInspection", fos1, true);
        /** 测试压缩方法2 */
//		List<File> fileList = new ArrayList<>();
//		fileList.add(new File("E:/emailTemplate.html"));
//		fileList.add(new File("E:/logobottom.jpg"));
//		FileOutputStream fos2 = new FileOutputStream(new File("E:/mytest02.zip"));
//		ZipUtil.toZip(fileList, fos2);
    }
}

Guess you like

Origin blog.csdn.net/xin_liu/article/details/108798478