Java学习者论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

手机号码,快捷登录

恭喜Java学习者论坛(https://www.javaxxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,购买链接:点击进入购买VIP会员
JAVA高级面试进阶视频教程Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程

Go语言视频零基础入门到精通

Java架构师3期(课件+源码)

Java开发全终端实战租房项目视频教程

SpringBoot2.X入门到高级使用教程

大数据培训第六期全套视频教程

深度学习(CNN RNN GAN)算法原理

Java亿级流量电商系统视频教程

互联网架构师视频教程

年薪50万Spark2.0从入门到精通

年薪50万!人工智能学习路线教程

年薪50万!大数据从入门到精通学习路线年薪50万!机器学习入门到精通视频教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程 MySQL入门到精通教程
查看: 284|回复: 0

[JavaIO学习]学习Java压缩技术(二)ZIP压缩

[复制链接]
  • TA的每日心情
    开心
    2021-3-12 23:18
  • 签到天数: 2 天

    [LV.1]初来乍到

    发表于 2014-10-28 23:56:14 | 显示全部楼层 |阅读模式
    查过相关资料后才知道,ZIP应该算作归档类的压缩算法,每一门学科都可深可浅!

    闲言少叙,先说ZIP压缩。
    zip压缩需要通过ZipOutputStream 执行write方法将压缩数据写到指定输出流中。
    注意,这里应先使用CheckedOutputStream 指定文件校验算法。(通常使用CRC32算法)。代码如下所示:
    CheckedOutputStream cos = new CheckedOutputStream(new FileOutputStream(destPath), new CRC32());
    ZipOutputStream zos = new ZipOutputStream(cos);
    [/code] 接下来,需要将待压缩文件以ZipEntry的方式追加到压缩文件中,如下所示:
                     /**
                     * 压缩包内文件名定义
                     *
                     * <pre>
                     * 如果有多级目录,那么这里就需要给出包含目录的文件名
                     * 如果用WinRAR打开压缩包,中文名将显示为乱码
                     * </pre>
                     */
                    ZipEntry entry = new ZipEntry(dir + file.getName());
                    zos.putNextEntry(entry);
    [/code] ZipEntry就是压缩包中的每一个实体!
    完成上述准备后,就可以执行压缩操作了。实际上,就是执行ZipOutputStream类的write方法,如下所示:

    BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
                    int count;
                    byte data[] = new byte[BUFFER];
                    while ((count = bis.read(data, 0, BUFFER)) != -1) {
                            zos.write(data, 0, count);
                    }
                    bis.close();
                            [/code] 当然,如果待添加的压缩项是一个目录。那么,需要通过递归的方式指定最终的压缩项。如果要添加一个空目录,貌似不可行!也许是我掌握的API还不够!

    递归构建目录压缩,代码如下:
            /**
             * 压缩
             *
             * @param srcFile
             *            源路径
             * @param zos
             *            ZipOutputStream
             * @param basePath
             *            压缩包内相对路径
             * @throws Exception
             */
            private static void compress(File srcFile, ZipOutputStream zos,
                            String basePath) throws Exception {
                    if (srcFile.isDirectory()) {
                            compressDir(srcFile, zos, basePath);
                    } else {
                            compressFile(srcFile, zos, basePath);
                    }
            }
            /**
             * 压缩目录
             *
             * @param dir
             * @param zos
             * @param basePath
             * @throws Exception
             */
            private static void compressDir(File dir, ZipOutputStream zos,
                            String basePath) throws Exception {
                    for (File file : dir.listFiles()) {
                            // 递归压缩
                            compress(file, zos, basePath + dir.getName() + PATH);
                    }
            }         [/code] 来个完整的压缩实现,代码如下所示:
    /**
    * 2010-4-12
    */
    package org.zlex.commons.io;
    import java.io.BufferedInputStream;
    import java.io.BufferedOutputStream;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.util.zip.CRC32;
    import java.util.zip.CheckedInputStream;
    import java.util.zip.CheckedOutputStream;
    import java.util.zip.ZipEntry;
    import java.util.zip.ZipInputStream;
    import java.util.zip.ZipOutputStream;
    /**
    * ZIP压缩工具
    *
    * @author  <a href="mailto:zlex.dongliang@gmail.com">梁栋</a>   
    * @since 1.0
    */
    public class ZipUtils {
            public static final String EXT = ".zip";
            private static final String BASE_DIR = "";
            private static final String PATH = "/";
            private static final int BUFFER = 1024;
            /**
             * 文件压缩
             *
             * @param srcPath
             *            源文件路径
             * @param destPath
             *            目标文件路径
             *
             */
            public static void compress(String srcPath, String destPath)
                            throws Exception {
                    File srcFile = new File(srcPath);
                    compress(srcFile, destPath);
            }
            /**
             * 压缩
             *
             * @param srcPath
             * @throws Exception
             */
            public static void compress(String srcPath) throws Exception {
                    File srcFile = new File(srcPath);
                    compress(srcFile);
            }
            /**
             * 压缩
             *
             * @param srcFile
             * @throws Exception
             */
            public static void compress(File srcFile) throws Exception {
                    String name = srcFile.getName();
                    String basePath = srcFile.getParent();
                    String destPath = basePath + name + EXT;
                    compress(srcFile, destPath);
            }
            /**
             * 压缩
             *
             * @param srcFile
             *            源路径
             * @param destPath
             *            目标路径
             * @throws Exception
             */
            public static void compress(File srcFile, File destFile) throws Exception {
                    // 对输出文件做CRC32校验
                    CheckedOutputStream cos = new CheckedOutputStream(new FileOutputStream(
                                    destFile), new CRC32());
                    ZipOutputStream zos = new ZipOutputStream(cos);
                    compress(srcFile, zos, BASE_DIR);
                    zos.closeEntry();
                    zos.flush();
                    zos.close();
            }
            /**
             * @param srcFile
             * @param destPath
             * @throws Exception
             */
            public static void compress(File srcFile, String destPath) throws Exception {
                    compress(srcFile, new File(destPath));
            }
            /**
             * 压缩
             *
             * @param srcFile
             *            源路径
             * @param zos
             *            ZipOutputStream
             * @param basePath
             *            压缩包内相对路径
             * @throws Exception
             */
            private static void compress(File srcFile, ZipOutputStream zos,
                            String basePath) throws Exception {
                    if (srcFile.isDirectory()) {
                            compressDir(srcFile, zos, basePath);
                    } else {
                            compressFile(srcFile, zos, basePath);
                    }
            }
            /**
             * 压缩目录
             *
             * @param dir
             * @param zos
             * @param basePath
             * @throws Exception
             */
            private static void compressDir(File dir, ZipOutputStream zos,
                            String basePath) throws Exception {
                    for (File file : dir.listFiles()) {
                            // 递归压缩
                            compress(file, zos, basePath + dir.getName() + PATH);
                    }
            }
            /**
             * 文件压缩
             *
             * @param file
             *            待压缩文件
             * @param zos
             *            ZipOutputStream
             * @param dir
             *            压缩文件中的当前路径
             * @throws Exception
             */
            private static void compressFile(File file, ZipOutputStream zos, String dir)
                            throws Exception {
                    /**
                     * 压缩包内文件名定义
                     *
                     * <pre>
                     * 如果有多级目录,那么这里就需要给出包含目录的文件名
                     * 如果用WinRAR打开压缩包,中文名将显示为乱码
                     * </pre>
                     */
                    ZipEntry entry = new ZipEntry(dir + file.getName());
                    zos.putNextEntry(entry);
                    BufferedInputStream bis = new BufferedInputStream(new FileInputStream(
                                    file));
                    int count;
                    byte data[] = new byte[BUFFER];
                    while ((count = bis.read(data, 0, BUFFER)) != -1) {
                            zos.write(data, 0, count);
                    }
                    bis.close();
            }
    }
                            [/code] 来做个简单的测试:

    import static org.junit.Assert.*;
    import org.junit.Test;
    /**
    *
    * @author 梁栋
    * @version 1.0
    * @since 1.0
    */
    public class ZipUtilsTest {
            /**
             *  
             */
            @Test
            public void test() throws Exception {
                    // 压缩文件
                    ZipUtils.compress("d:\f.txt");
                    // 压缩目录
                    ZipUtils.compress("d:\fd");
            }
    }                     [/code] 现在用WinRAR打开看看,是不是效果几乎一致?

    当然,上述代码有所不足之处:
    1.中文名称乱码问题。用java原生ZIP实现压缩后得到的压缩包,与系统的字符集不同,文件/目录名将出现乱码
    2.空目录忽略压缩。对于空目录,我还真没找到如何压缩的方法。单纯添加ZipEntry,将得到一个无法识别的文件。是我对其属性设置不够?!


       
         
         
          
          

            
          

            
          
         
       

      


    源码下载:http://file.javaxxz.com/2014/10/28/235614125.zip
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|Java学习者论坛 ( 声明:本站资料整理自互联网,用于Java学习者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2025-2-26 04:04 , Processed in 0.370689 second(s), 46 queries .

    Powered by Discuz! X3.4

    © 2001-2017 Comsenz Inc.

    快速回复 返回顶部 返回列表