使用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);
            }
        }
    }

压缩前的目标文件如下:

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

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方法来处理:

由于文件夹结构如下:

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

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包解压后,直接出现文件,没有最外层文件夹:

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

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

程序运行示例截图: 

示例代码:

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方法工具中的方法:

/**
     * 使用给定密码压缩指定文件或文件夹到指定位置.
     * <p>
     * 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<File> temp = new ArrayList<File>();
                            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<File> temp = new ArrayList<File>();
                    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();
        }

生成效果:

注意:

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

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

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

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

  • 14
    点赞
  • 74
    收藏
    觉得还不错? 一键收藏
  • 17
    评论
Java源码100个设计实例, 大量 实例,可以作为你的学习设计参考。 实例如下: Applet钢琴模拟程序java源码 Calendar万年历 copass源代码.rar DataBuffer在Java使用ADO.NET.rar EJB 模拟银行ATM流程及操作源代码 ejbCreate函数用于初始化一个EJB实例 EJB中JNDI的使用源码例子 EJB的真实世界模型(源代码).rar ftp文件传输 ftp简易服务器.rar HAHA CHAT Java仿QQ聊天程序源代码.rar html 标记大全.rar iCHAT聊天室基于Java.rar IP定位器.rar J2ME优化压缩PNG文件.rar J2ME冒险游戏CASPER源代码.rar J2me月光战机游戏源码.rar J2ME黑白棋游戏手机 v2.1完整源码.rar JasperReports 报表类库v3.5.rar Java 3DMenu 界面源码.rar Java 3D魔方游戏源码及中文注释.rar Java EJB中有、无状态SessionBean的两个例子 Java Socket 聊天通信演示代码 java Socket通信实现.rar Java Telnet客户端实例源码 Java zip压缩查看程序源码.rar java 一个消息发布网站.rar Java 数字签名、数字证书生成源码.rar Java 的酒店系统,貌似完整.rar Java 电梯模拟程序 v2.0.rar Java 组播组中发送和接受数据实例 Java 飞机订票.rar Java 高考信息管理系统 SQL数据库.rar Java (Jsp)制作简单的表单程序.rar Java+ajax写的登录实例.rar JAVA+JSP的聊天室.rar Java+MsSQL超市进销存(毕业设计及答辩资料).rar Java+sqlserver2000做的员工管理系统.rar Java+SQL信用卡管理系统源代码.rar Java+XML写的RSS阅读器.rar Java+XML日程提醒系统.rar Java24点游戏逼真图形代码.rar JavaScript万年历.rar Java二进制IO类与文件复制操作实例.rar Java从压缩中提取文件.rar Java从网络取得文件.rar Java仓库管理系统,Access数据库.rar Java仿Vista界面风格的登录窗口.rar Java仿千千静听音乐播放器源代码.rar Java企业人事管理系统源码.rar java俄罗斯方块 java凭图游戏 Java利用DES私钥对称加密代码实例 Java加密解密工具集 JCT v1.0源码.rar Java半透明图片实现的步骤及源代码.rar Java右键弹出菜单源码 Java吃豆子游戏源代码.rar Java图片加水印,支持旋转和透明度设置 Java圆形按钮实例代码,含注释 Java圆形电子时钟源代码 Java多用户聊天室程序(毕业设计).rar Java大型CERP进销存系统.rar Java存储与读取对象.rar Java局域网通信——飞鸽传书源代码.rar JAVA帮助视图组件库 Help GUI 1.1源代码.rar JAVA开发的打字软件源程序.rar Java开发的简单WEB服务器源码.rar Java数据压缩与传输实例 Java数组倒置 Java日期选择控件完整源代码.rar Java机车狂飙源代码.rar Java模仿的MSN聊天软件.rar java模拟掷骰子2个 Java毕业论文:搜索引擎系统附源代码.rar JAVA毕业设计_员工管理系统含文档.rar Java毕业设计一款J2me飞行射击游戏.rar java求一个整数的因子 Java波浪文字制作方法及源代码.rar Java火影忍者游戏源代码.rar JAVASwing星际争霸游戏源代码.rar Java生成密钥的实例 Java电子相册源码.rar Java目录监视器源程序.zip JAVA短信网关平台(值得一看).rar Java绘制图片火焰效果.rar Java编写的HTML浏览器.rar Java编写的山寨QQ,多人聊天+用户在线.rar Java编写的显示器显示模式检测程序.rar Java编写的网页魔方游戏.rar java聊天室 Java聊天程序(JBuilder).rar Java聊天程序,括服务端和客户端.rar Java聊天软件Visual Chat v1.91源码.rar Java访问权限控制源代码.rar Java读写文本文件的示例代码 Java赌神游戏网络源代码.rar Java超市管理,SQL2000+源代码.rar Java超市进销存系统.rar Java软件度量源码.ra
可以使用Apache PDFBox库来生成OFD文件,因为OFD文件本质上是一个含XML和一些其他文件的ZIP文件。以下是一个示例代码: ```java import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBException; import javax.xml.bind.Marshaller; public class OFDGenerator { public static void generateOFD() throws IOException, JAXBException { // 创建OFD文件夹 File ofdFolder = new File("example.ofd"); ofdFolder.mkdirs(); // 创建OFD.xml文件 OFD ofd = new OFD(); JAXBContext jaxbContext = JAXBContext.newInstance(OFD.class); Marshaller marshaller = jaxbContext.createMarshaller(); marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); marshaller.marshal(ofd, new File(ofdFolder, "OFD.xml")); // 将OFD.xml和其他文件压缩为OFD文件 ZipOutputStream zipOut = new ZipOutputStream(new FileOutputStream("example.ofd")); addToZipFile("OFD.xml", ofdFolder.getAbsolutePath(), zipOut); // 添加其他文件 zipOut.close(); } private static void addToZipFile(String fileName, String folderName, ZipOutputStream zipOut) throws IOException { File file = new File(folderName + "/" + fileName); ZipEntry zipEntry = new ZipEntry(fileName); zipOut.putNextEntry(zipEntry); FileInputStream fis = new FileInputStream(file); byte[] bytes = new byte[1024]; int length; while ((length = fis.read(bytes)) >= 0) { zipOut.write(bytes, 0, length); } fis.close(); } } ``` 请注意,这只是一个简单的示例,你需要根据你的具体需求来更改代码。此外,你还需要确保所使用的Apache PDFBox库本支持OFD生成

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值