Java 压缩多个文件为zip包(中间不生成临时文件,直接压缩为zip二进制流),以及解压zip包二进制流为文件

50 篇文章 2 订阅

Java 压缩多个文件为zip包及解压zip包以及压缩多文件为zip文件流解压zip二进制流(中间不生成临时文件,直接压缩为zip二进制流,并验证解压)

这篇博客将提供俩种方法,

  1. 提前生成要压缩的多个文件,然后读取文件夹多层或一层去遍历压缩zip包
  2. 直接用原始文件名称及二进制流,压缩返回zip包二进制流,中间不生成冗余文件;
    很明显方法2更优一些;
  3. 解压zip文件或者zip文件流验证;

1. 效果图

压缩俩个文件到zip包,并分别解析zip包文件及zip二进制流,打印文件及文件内容详情效果图如下:

在这里插入图片描述

2. 源码

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();
        }
    }
}
  • 3
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
Java调用Zip类批量压缩多个文件,此前有一个是压缩单个文件,也可参考,相关代码中可找到此源码。   public class ZipDemo extends JFrame{   JFileChooser fileChooser; //文件选择器   JList fileList; //待压缩文件列表   Vector files; //文件数据(待压缩文件)   JButton jbAdd; //增加文件按钮   JButton jbDelete; //删除文件按钮   JButton jbZip; //压缩按钮   JTextField target; //目标文件文本域   public ZipDemo(){   super("用ZIP压缩多个文件"); //调用父类构造函数   fileChooser=new JFileChooser(); //实例化文件选择器   files=new Vector(); //实例化文件数据Vector   fileList=new JList(files); //实例化已选择文件列表   jbAdd=new JButton("增加"); //实例化按钮组件   jbDelete=new JButton("删除");   jbZip=new JButton("压缩");   target=new JTextField(18);   JPanel panel=new JPanel(); //实例化面板,用于容纳按钮   panel.add(jbAdd); //增加组件到面板上   panel.add(jbDelete);   panel.add(jbZip);   JPanel panel2=new JPanel();   panel2.add(new JLabel("目标文件"));   panel2.add(target);   JScrollPane jsp=new JScrollPane(fileList);   Container container=getContentPane(); //得到容器   container.add(panel2,BorderLayout.NORTH); //增加组件到容器   container.add(jsp,BorderLayout.CENTER);   container.add(panel,BorderLayout.SOUTH);   jsp.setBorder(BorderFactory.createEmptyBorder(10,10,10,10)); //设置边界
上传二进制: ```java public void uploadFile(byte[] fileBytes, String fileName) { try { String url = "http://example.com/upload"; // 上传文件的接口URL HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection(); conn.setRequestMethod("POST"); conn.setDoOutput(true); conn.setRequestProperty("Content-Type", "application/zip"); // 设置上传文件文件类型 conn.setRequestProperty("Content-Disposition", "attachment;filename=\"" + fileName + "\""); // 设置上传文件文件名 OutputStream outputStream = conn.getOutputStream(); outputStream.write(fileBytes); outputStream.flush(); outputStream.close(); int responseCode = conn.getResponseCode(); if (responseCode == HttpURLConnection.HTTP_OK) { // 上传成功 } else { // 上传失败 } } catch (Exception e) { e.printStackTrace(); } } ``` 下载二进制: ```java public byte[] downloadFile(String fileUrl) { byte[] fileBytes = null; try { HttpURLConnection conn = (HttpURLConnection) new URL(fileUrl).openConnection(); conn.setRequestMethod("GET"); conn.setDoInput(true); int responseCode = conn.getResponseCode(); if (responseCode == HttpURLConnection.HTTP_OK) { InputStream inputStream = conn.getInputStream(); ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); byte[] buffer = new byte[1024]; int len; while ((len = inputStream.read(buffer)) != -1) { byteArrayOutputStream.write(buffer, 0, len); } fileBytes = byteArrayOutputStream.toByteArray(); byteArrayOutputStream.close(); inputStream.close(); } else { // 下载失败 } } catch (Exception e) { e.printStackTrace(); } return fileBytes; } ``` 将二进制写入文件: ```java public void writeBytesToFile(byte[] fileBytes, String filePath) { try { FileOutputStream outputStream = new FileOutputStream(filePath); outputStream.write(fileBytes); outputStream.close(); } catch (Exception e) { e.printStackTrace(); } } ``` 将文件读取为二进制: ```java public byte[] readFileToBytes(String filePath) { byte[] fileBytes = null; try { FileInputStream inputStream = new FileInputStream(filePath); ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); byte[] buffer = new byte[1024]; int len; while ((len = inputStream.read(buffer)) != -1) { byteArrayOutputStream.write(buffer, 0, len); } fileBytes = byteArrayOutputStream.toByteArray(); byteArrayOutputStream.close(); inputStream.close(); } catch (Exception e) { e.printStackTrace(); } return fileBytes; } ``` 将二进制存入数据库: ```java public void saveBytesToDatabase(byte[] fileBytes, String fileName) { Connection conn = null; PreparedStatement pstmt = null; try { Class.forName("com.mysql.jdbc.Driver"); String url = "jdbc:mysql://localhost:3306/test"; conn = DriverManager.getConnection(url, "root", "password"); String sql = "INSERT INTO files (name, content) VALUES (?, ?)"; pstmt = conn.prepareStatement(sql); pstmt.setString(1, fileName); pstmt.setBytes(2, fileBytes); pstmt.executeUpdate(); } catch (Exception e) { e.printStackTrace(); } finally { try { if (pstmt != null) { pstmt.close(); } if (conn != null) { conn.close(); } } catch (Exception e) { e.printStackTrace(); } } } ``` 从数据库读取二进制: ```java public byte[] readBytesFromDatabase(String fileName) { byte[] fileBytes = null; Connection conn = null; PreparedStatement pstmt = null; ResultSet rs = null; try { Class.forName("com.mysql.jdbc.Driver"); String url = "jdbc:mysql://localhost:3306/test"; conn = DriverManager.getConnection(url, "root", "password"); String sql = "SELECT content FROM files WHERE name = ?"; pstmt = conn.prepareStatement(sql); pstmt.setString(1, fileName); rs = pstmt.executeQuery(); if (rs.next()) { fileBytes = rs.getBytes("content"); } } catch (Exception e) { e.printStackTrace(); } finally { try { if (rs != null) { rs.close(); } if (pstmt != null) { pstmt.close(); } if (conn != null) { conn.close(); } } catch (Exception e) { e.printStackTrace(); } } return fileBytes; } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序媛一枚~

您的鼓励是我创作的最大动力。

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值