Java compresses multiple files into a zip package (no temporary files are generated in the middle, directly compressed into a zip binary stream), and decompresses the zip package binary stream into a file

Java compresses multiple files into zip packages and decompresses zip packages and compresses multiple files into zip file streams and decompresses zip binary streams (temporary files are not generated in the middle, directly compressed into zip binary streams, and verified for decompression)

This blog will provide two methods,

  1. Generate multiple files to be compressed in advance, and then read multiple layers or layers of folders to traverse the compressed zip package
  2. Directly use the original file name and binary stream, compress and return the binary stream of the zip package, without generating redundant files in the middle;
    it is obvious that method 2 is better;
  3. Decompress zip file or zip file stream verification;

1. Rendering

Compress the two files into a zip package, and analyze the zip package file and the zip binary stream respectively, print the file and the detailed rendering of the file content as follows:

insert image description here

2. Source code

import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;


public class FileUtil {
    
    

    public static void main(String[] args) throws Exception {
    
    
        long timeStamp = System.currentTimeMillis();
        String uuid = UUID.randomUUID().toString();
        // 生成本地文件,然后压缩,压缩完成清除本地文件及冗余文件夹
        zipTest1(uuid, timeStamp);

        // 不生成中间文件,直接使用文件名称+文件流进行压缩 更优
        zipTest2(uuid, timeStamp);
    }

    private static void zipTest2(String uuid, long timeStamp) throws IOException {
    
    
        String zipFileName = String.format("%s_%s.zip", uuid, timeStamp);
        String imgFileName = String.format("%s_%s_%s.json", "img", uuid, timeStamp);
        String referInfoFile = String.format("%s_%s_%s.json", "ref", uuid, timeStamp);

        String[] fileNames = new String[]{
    
    imgFileName, referInfoFile};
        List<byte[]> bytesList = new ArrayList<>();
        byte[] file0 = imgFileName.toString().getBytes();
        byte[] file1 = referInfoFile.toString().getBytes();
        bytesList.add(file0);
        bytesList.add(file1);

        // zip压缩流
        byte[] rodZip = packageZipToBytes(fileNames, bytesList);

        readAndParseZip(zipFileName, rodZip);
    }

    private static void zipTest1(String uuid, long timeStamp) throws Exception {
    
    
        String path = System.getProperty("user.dir") + File.separator + uuid + "_" + timeStamp + File.separator;
        String resPath = System.getProperty("user.dir") + File.separator + "out" + File.separator + uuid + "_" + timeStamp;

        deleteDirectory(path);
        delOrCreateDir(path);
        delOrCreateDir(resPath);
        String imgFileName = String.format("%s%s_%s_%s.json", path, "img", uuid, timeStamp);
        String referInfoFile = String.format("%s%s_%s_%s.json", path, "ref", uuid, timeStamp);
        try (FileWriter fileWriter = new FileWriter(referInfoFile)) {
    
    
            fileWriter.write(referInfoFile.toString());
        }
        try (FileWriter fileWriter = new FileWriter(imgFileName)) {
    
    
            fileWriter.write(imgFileName.toString());
        }

        System.out.println("zip start ---------------" + System.currentTimeMillis());
        FileUtil test3 = new FileUtil();
        String packagePath = path;  //选中的文件夹
        test3.packageZip(packagePath, resPath + ".zip");
        System.out.println("zip finish ---------------" + System.currentTimeMillis());

        // 删除冗余文件,文件夹
        deleteDirectory(path);
        deleteDirectory(resPath);
        deleteDirectory(resPath);
    }

    /**
     * 压缩多个文件为zip包文件流
     *
     * @param fileNames 文件名称
     * @param byteLists 文件流
     * @return
     */
    public static byte[] packageZipToBytes(String[] fileNames, List<byte[]> byteLists) throws IOException {
    
    
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ZipOutputStream zipOutputStream = null;
        try {
    
    
            zipOutputStream = new ZipOutputStream(bos);
            for (int i = 0; i < fileNames.length; i++) {
    
    
                String fileName = fileNames[i];
                fileName = fileName.substring(fileName.lastIndexOf(File.separator) + 1);
                byte[] content = byteLists.get(i);
                // 依次对每个文件都压缩
                try {
    
    
                    zipOutputStream.putNextEntry(new ZipEntry(fileName));
                    zipOutputStream.write(content);
                } catch (IOException e) {
    
    
                    throw new RuntimeException(e);
                }
            }
            zipOutputStream.close();
            bos.close();
        } catch (FileNotFoundException e) {
    
    
            throw new RuntimeException(e);
        } catch (IOException e) {
    
    
            throw new RuntimeException(e);
        }

        byte[] zipOutBytes = bos.toByteArray();
/*        OutputStream fos = new FileOutputStream("D:\\study\\ark-common-model\\out\\aaaaaaaa_1689583754986.zip");
        fos.write(zipOutBytes, 0, zipOutBytes.length);
        fos.close();*/

        return zipOutBytes;
    }

    private static void readAndParseZip(String zipFilePath, byte[] rodZip) {
    
    
        ByteArrayInputStream fis = null;
        FileInputStream fileInputStream = null;
        ZipInputStream zis = null;
        try {
    
    
            if (rodZip != null) {
    
    
                fis = new ByteArrayInputStream(rodZip);
                zis = new ZipInputStream(fis);
            } else {
    
    
                fileInputStream = new FileInputStream(zipFilePath);
                zis = new ZipInputStream(fileInputStream);
            }

            ZipEntry zipEntry = zis.getNextEntry();
            while (zipEntry != null) {
    
    
                // 如果该项是一个文件
                if (!zipEntry.isDirectory()) {
    
    
                    String fileName = zipEntry.getName();
                    ByteArrayOutputStream bos = new ByteArrayOutputStream();

                    byte[] buffer = new byte[1024];
                    int len;
                    while ((len = zis.read(buffer)) > 0) {
    
    
                        bos.write(buffer, 0, len);
                    }
                    // 将解压出的文件流输出到控制台
                    String content = bos.toString();
                    System.out.println("fileName: " + fileName + ",content: " + content);
                }
                zis.closeEntry();
                zipEntry = zis.getNextEntry();
            }

            zis.close();
            fis.close();
        } catch (IOException e) {
    
    
            e.printStackTrace();
        }
    }

    public static void delOrCreateDir(String imgPath) {
    
    
        File file = new File(imgPath);

        if (!file.getParentFile().exists()) {
    
    
            //上级目录不存在,创建上级目录
            file.getParentFile().mkdirs();
        } else {
    
    
//            FileUtils.deleteFolder(imgPath);
        }
        file.mkdirs();
    }

    /**
     * 根据路径删除指定的目录或文件,无论存在与否
     *
     * @param sPath 要删除的目录或文件
     * @return 删除成功返回 true,否则返回 false。
     */
    public static boolean deleteFolder(String sPath) {
    
    
        boolean flag = false;
        File file = new File(sPath);
        // 判断目录或文件是否存在
        if (!file.exists()) {
    
      // 不存在返回 false
            return flag;
        } else {
    
    
            // 判断是否为文件
            if (file.isFile()) {
    
      // 为文件时调用删除文件方法
                return deleteFile(sPath);
            } else {
    
      // 为目录时调用删除目录方法
                return deleteDirectory(sPath);
            }
        }
    }

    /**
     * 删除单个文件
     *
     * @param sPath 被删除文件的文件名
     * @return 单个文件删除成功返回true,否则返回false
     */
    public static boolean deleteFile(String sPath) {
    
    
        boolean flag = false;
        File file = new File(sPath);
        // 路径为文件且不为空则进行删除
        if (file.isFile() && file.exists()) {
    
    
            file.delete();
            flag = true;
        }
        return flag;
    }

    /**
     * 删除目录(文件夹)以及目录下的文件
     *
     * @param sPath 被删除目录的文件路径
     * @return 目录删除成功返回true,否则返回false
     */
    public static boolean deleteDirectory(String sPath) {
    
    
        boolean flag = false;
        //如果sPath不以文件分隔符结尾,自动添加文件分隔符
        if (!sPath.endsWith(File.separator)) {
    
    
            sPath = sPath + File.separator;
        }
        File dirFile = new File(sPath);
        //如果dir对应的文件不存在,或者不是一个目录,则退出
        if (!dirFile.exists() || !dirFile.isDirectory()) {
    
    
            return false;
        }
        flag = true;
        //删除文件夹下的所有文件(包括子目录)
        File[] files = dirFile.listFiles();
        for (int i = 0; i < files.length; i++) {
    
    
            //删除子文件
            if (files[i].isFile()) {
    
    
                flag = deleteFile(files[i].getAbsolutePath());
                if (!flag) {
    
    
                    break;
                }
            } //删除子目录
            else {
    
    
                flag = deleteDirectory(files[i].getAbsolutePath());
                if (!flag) {
    
    
                    break;
                }
            }
        }
        if (!flag) {
    
    
            return false;
        }
        //删除当前目录
        if (dirFile.delete()) {
    
    
//            dirFile.getParentFile().delete();
            return true;
        } else {
    
    
//            dirFile.getParentFile().delete();
            return false;
        }
    }


    public void packageZip(String filesPath, String resPath) throws Exception {
    
    
        // 要被压缩的文件夹
        File file = new File(filesPath);   //需要压缩的文件夹
        File zipFile = new File(resPath);
        ZipOutputStream zipOut = new ZipOutputStream(new FileOutputStream(zipFile));
        isDirectory(file, zipOut, "", true);   //判断是否为文件夹
        zipOut.close();
    }

    public void isDirectory(File file, ZipOutputStream zipOutputStream, String filePath, boolean flag) throws
            IOException {
    
    
        //判断是否为问加减
        if (file.isDirectory()) {
    
    
            File[] files = file.listFiles();  //获取该文件夹下所有文件(包含文件夹)
            filePath = flag == true ? file.getName() : filePath + File.separator + file.getName();   //首次为选中的文件夹,即根目录,之后递归实现拼接目录
            for (int i = 0; i < files.length; ++i) {
    
    
                //判断子文件是否为文件夹
                if (files[i].isDirectory()) {
    
    
                    System.out.println("-----" + files[i].getName());
                    //进入递归,flag置false 即当前文件夹下仍包含文件夹
                    isDirectory(files[i], zipOutputStream, filePath, false);
                } else {
    
    
                    System.out.println("fileName: " + files[i].getName());
                    //不为文件夹则进行压缩
                    InputStream input = new FileInputStream(files[i]);
                    zipOutputStream.putNextEntry(new ZipEntry(files[i].getName()));
                    int temp = 0;
                    while ((temp = input.read()) != -1) {
    
    
                        zipOutputStream.write(temp);
                    }
                    input.close();
                }
            }
        } else {
    
    
            //将子文件夹下的文件进行压缩
            InputStream input = new FileInputStream(file);
            zipOutputStream.putNextEntry(new ZipEntry(file.getPath()));
            int temp = 0;
            while ((temp = input.read()) != -1) {
    
    
                zipOutputStream.write(temp);
            }
            input.close();
        }
    }
}

Guess you like

Origin blog.csdn.net/qq_40985985/article/details/131780780