批量打包成ZIP压缩文件

一、前言

  在开发的过程中,我们有时候会遇到提供数据下载的功能,当数据量较大的时候,可能需要分开几个文件,然后再在后台打包成ZIP压缩文件,传送到前台。之前博客中有提及过如何用Java实现添加到压缩文件中,当时只讨论了如何单个文件添加压缩文件,这篇文章将讨论多文件压缩的问题。

二、多文件压缩

    @Test
    public void test() throws Exception{
        // 被压缩文件
        File file = new File("C:\Users\Administrator\Desktop\文件a.pdf");
        File file2 = new File("C:\Users\Administrator\Desktop\文件b.pdf");

        // 输出文件outputStream
        File outFile = new File("C:\Users\Administrator\Desktop\压缩文件.zip");
        FileOutputStream outputStream = new FileOutputStream(outFile);
        ZipOutputStream zipOutputStream = new ZipOutputStream(outputStream);

        // 读取file文件
        FileInputStream inputStream = new FileInputStream(file);
        byte[] bytes = new byte[inputStream.available()];
        inputStream.read(bytes);
        ZipEntry zipEntry = new ZipEntry(file.getName());
        zipOutputStream.putNextEntry(zipEntry);
        zipOutputStream.write(bytes);
        zipOutputStream.flush();

        // 读取file2文件
        inputStream = new FileInputStream(file2);
        bytes = new byte[inputStream.available()];
        inputStream.read(bytes);
        zipEntry = new ZipEntry(file2.getName());
        zipOutputStream.putNextEntry(zipEntry);
        zipOutputStream.write(bytes);
        zipOutputStream.flush();

        // 关闭各种流
        zipOutputStream.closeEntry();
        inputStream.close();
        zipOutputStream.close();
        outputStream.close();

    }

  上述这段代码,可以实现两个文件添加到ZIP压缩文件中。这种面相过程的写法,在某种程度上符合人的思考逻辑与顺序。但这种写法代码的耦合性高,代码复用性差。不是像上述代码那样写死,而是需要到本地文件中去取,又或者从数据库中拿,还是用POI读取Excel的方式获取文件路径,都不太好处理。人为操作的依赖性强。

三、基于面相对象多文件添加ZIP文件

    /**
     * 文件读取缓冲区大小
     */
    private static final int CACHE_SIZE = 1024;

    @Test
    public void test2() throws Exception{
        // 获取文件列表
        List<File> fileList = this.getFileList();
        // 压缩到ZIP文件中
        this.toZIP(fileList);
    }

    /**
     * 获取文件列表
     * @return
     */
    private List<File> getFileList(){
        List<File> fileList = new ArrayList<>();
        File file = new File("C:\Users\Administrator\Desktop\文件a.pdf");
        File file2 = new File("C:\Users\Administrator\Desktop\文件b.pdf");
        fileList.add(file);
        fileList.add(file2);
        return fileList;
    }

    /**
     * 压缩到ZIP文件中
     * @param fileList
     * @throws Exception
     */
    private void toZIP(List<File> fileList) throws Exception{
        // 定义读取问价及读取数组
        FileInputStream inputStream = null;
        byte[] bytes = null;

        // 输出文件outputStream
        File outFile = new File("C:\Users\Administrator\Desktop\压缩文件.zip");
        FileOutputStream outputStream = new FileOutputStream(outFile);
        ZipOutputStream zipOutputStream = new ZipOutputStream(outputStream);

        // 循环写入ZIP文件
        for(File file : fileList){
            // 定义实体
            ZipEntry zipEntry = new ZipEntry(file.getName());
            zipOutputStream.putNextEntry(zipEntry);
            // 将文件读到数组中
            inputStream = new FileInputStream(file);
            // 整体读到内存(文件过大会内存溢出)
            //bytes = new byte[inputStream.available()];
            //inputStream.read(bytes);
            //zipOutputStream.write(bytes);
            // 分批读写
            bytes = new byte[CACHE_SIZE];
            int len = 0;
            while((len = inputStream.read(bytes)) != -1){
                zipOutputStream.write(bytes);
            }
            zipOutputStream.flush();
        }
        // 关闭各种流
        zipOutputStream.closeEntry();
        inputStream.close();
        zipOutputStream.close();
        outputStream.close();
    }

   该断代码中,重新划分获取文件的模块,同时增加的循环逻辑,提高代码的复用。在之前的文章中和上面的代码中,都需全部数据获取到数组中,为何这里需要分批读取呢?当文件大的时候,这样可以方式内存溢出的问题。而且通常开发者的电脑配置(内存)会高于服务器的内存配置,在开发者的电脑没问题,不代表生产环境没有问题,还是推荐使用分批读取。

Reference:

ryelqy, Java实现添加压缩文件, https://www.cnblogs.com/ryelqy/p/10104167.html

原文地址:https://www.cnblogs.com/ryelqy/p/14382467.html