zoukankan      html  css  js  c++  java
  • Java压缩技术(三) ZIP解压缩——Java原生实现

    原文:http://snowolf.iteye.com/blog/642492

    JavaEye的朋友跟我说:“你一口气把ZIP压缩和解压缩都写到一个帖子里,我看起来很累,不如分开好阅读”。ok,面向读者需求,我做调整,这里单说ZIP解压缩!

    解压缩与压缩运作方式相反,原理大抵相同,由ZipInputStream通过read方法对数据解压,同时需要通过CheckedInputStream设置冗余校验码,如:

    Java代码  收藏代码
    1. CheckedInputStream cis = new CheckedInputStream(new FileInputStream(  
    2.         srcFile), new CRC32());  
    3.   
    4. ZipInputStream zis = new ZipInputStream(cis);  



    需要注意的是,在构建解压文件时,需要考虑目录的自动创建,这里通过递归方式逐层创建父目录,如下所示:

    Java代码  收藏代码
    1. /** 
    2.  * 文件探针 
    3.  *  
    4.  *  
    5.  * 当父目录不存在时,创建目录! 
    6.  *  
    7.  *  
    8.  * @param dirFile 
    9.  */  
    10. private static void fileProber(File dirFile) {  
    11.   
    12.     File parentFile = dirFile.getParentFile();  
    13.     if (!parentFile.exists()) {  
    14.   
    15.         // 递归寻找上级目录  
    16.         fileProber(parentFile);  
    17.   
    18.         parentFile.mkdir();  
    19.     }  
    20.   
    21. }  



    在压缩的时候,我们是将一个一个文件作为压缩添加项(ZipEntry)添加至压缩包中,解压缩就要将一个一个压缩项从压缩包中提取出来,如下所示:

    Java代码  收藏代码
    1. /** 
    2.  * 文件 解压缩 
    3.  *  
    4.  * @param destFile 
    5.  *            目标文件 
    6.  * @param zis 
    7.  *            ZipInputStream 
    8.  * @throws Exception 
    9.  */  
    10. private static void decompress(File destFile, ZipInputStream zis)  
    11.         throws Exception {  
    12.   
    13.     ZipEntry entry = null;  
    14.     while ((entry = zis.getNextEntry()) != null) {  
    15.   
    16.         // 文件  
    17.         String dir = destFile.getPath() + File.separator + entry.getName();  
    18.   
    19.         File dirFile = new File(dir);  
    20.   
    21.         // 文件检查  
    22.         fileProber(dirFile);  
    23.   
    24.             if (entry.isDirectory()){  
    25.                 dirFile.mkdirs();  
    26.             } else {  
    27.             decompressFile(dirFile, zis);  
    28.             }  
    29.   
    30.             zis.closeEntry();  
    31.     }  
    32. }  





    最核心的解压缩实现,其实与压缩实现非常相似,代码如下所示:

    Java代码  收藏代码
    1. /** 
    2.  * 文件解压缩 
    3.  *  
    4.  * @param destFile 
    5.  *            目标文件 
    6.  * @param zis 
    7.  *            ZipInputStream 
    8.  * @throws Exception 
    9.  */  
    10. private static void decompressFile(File destFile, ZipInputStream zis)  
    11.         throws Exception {  
    12.   
    13.     BufferedOutputStream bos = new BufferedOutputStream(  
    14.             new FileOutputStream(destFile));  
    15.   
    16.     int count;  
    17.     byte data[] = new byte[BUFFER];  
    18.     while ((count = zis.read(data, 0, BUFFER)) != -1) {  
    19.         bos.write(data, 0, count);  
    20.     }  
    21.   
    22.     bos.close();  
    23. }  





    来个完整的解压缩实现,代码如下:

    Java代码  收藏代码
    1. /** 
    2.  * 2010-4-12 
    3.  */  
    4. package org.zlex.commons.io;  
    5.   
    6. import java.io.BufferedInputStream;  
    7. import java.io.BufferedOutputStream;  
    8. import java.io.File;  
    9. import java.io.FileInputStream;  
    10. import java.io.FileOutputStream;  
    11. import java.util.zip.CRC32;  
    12. import java.util.zip.CheckedInputStream;  
    13. import java.util.zip.CheckedOutputStream;  
    14. import java.util.zip.ZipEntry;  
    15. import java.util.zip.ZipInputStream;  
    16. import java.util.zip.ZipOutputStream;  
    17.   
    18. /** 
    19.  * ZIP压缩工具 
    20.  *  
    21.  * @author 梁栋    
    22.  * @since 1.0 
    23.  */  
    24. public class ZipUtils {  
    25.   
    26.     public static final String EXT = ".zip";  
    27.     private static final String BASE_DIR = "";  
    28.     private static final String PATH = File.separator;  
    29.     private static final int BUFFER = 1024;  
    30.   
    31.     /** 
    32.      * 文件 解压缩 
    33.      *  
    34.      * @param srcPath 
    35.      *            源文件路径 
    36.      *  
    37.      * @throws Exception 
    38.      */  
    39.     public static void decompress(String srcPath) throws Exception {  
    40.         File srcFile = new File(srcPath);  
    41.   
    42.         decompress(srcFile);  
    43.     }  
    44.   
    45.     /** 
    46.      * 解压缩 
    47.      *  
    48.      * @param srcFile 
    49.      * @throws Exception 
    50.      */  
    51.     public static void decompress(File srcFile) throws Exception {  
    52.         String basePath = srcFile.getParent();  
    53.         decompress(srcFile, basePath);  
    54.     }  
    55.   
    56.     /** 
    57.      * 解压缩 
    58.      *  
    59.      * @param srcFile 
    60.      * @param destFile 
    61.      * @throws Exception 
    62.      */  
    63.     public static void decompress(File srcFile, File destFile) throws Exception {  
    64.   
    65.         CheckedInputStream cis = new CheckedInputStream(new FileInputStream(  
    66.                 srcFile), new CRC32());  
    67.   
    68.         ZipInputStream zis = new ZipInputStream(cis);  
    69.   
    70.         decompress(destFile, zis);  
    71.   
    72.         zis.close();  
    73.   
    74.     }  
    75.   
    76.     /** 
    77.      * 解压缩 
    78.      *  
    79.      * @param srcFile 
    80.      * @param destPath 
    81.      * @throws Exception 
    82.      */  
    83.     public static void decompress(File srcFile, String destPath)  
    84.             throws Exception {  
    85.         decompress(srcFile, new File(destPath));  
    86.   
    87.     }  
    88.   
    89.     /** 
    90.      * 文件 解压缩 
    91.      *  
    92.      * @param srcPath 
    93.      *            源文件路径 
    94.      * @param destPath 
    95.      *            目标文件路径 
    96.      * @throws Exception 
    97.      */  
    98.     public static void decompress(String srcPath, String destPath)  
    99.             throws Exception {  
    100.   
    101.         File srcFile = new File(srcPath);  
    102.         decompress(srcFile, destPath);  
    103.     }  
    104.   
    105.     /** 
    106.      * 文件 解压缩 
    107.      *  
    108.      * @param destFile 
    109.      *            目标文件 
    110.      * @param zis 
    111.      *            ZipInputStream 
    112.      * @throws Exception 
    113.      */  
    114.     private static void decompress(File destFile, ZipInputStream zis)  
    115.             throws Exception {  
    116.   
    117.         ZipEntry entry = null;  
    118.         while ((entry = zis.getNextEntry()) != null) {  
    119.   
    120.             // 文件  
    121.             String dir = destFile.getPath() + File.separator + entry.getName();  
    122.   
    123.             File dirFile = new File(dir);  
    124.   
    125.             // 文件检查  
    126.             fileProber(dirFile);  
    127.   
    128.             if (entry.isDirectory()) {  
    129.                 dirFile.mkdirs();  
    130.             } else {  
    131.                 decompressFile(dirFile, zis);  
    132.             }  
    133.   
    134.             zis.closeEntry();  
    135.         }  
    136.     }  
    137.   
    138.     /** 
    139.      * 文件探针 
    140.      *  
    141.      *  
    142.      * 当父目录不存在时,创建目录! 
    143.      *  
    144.      *  
    145.      * @param dirFile 
    146.      */  
    147.     private static void fileProber(File dirFile) {  
    148.   
    149.         File parentFile = dirFile.getParentFile();  
    150.         if (!parentFile.exists()) {  
    151.   
    152.             // 递归寻找上级目录  
    153.             fileProber(parentFile);  
    154.   
    155.             parentFile.mkdir();  
    156.         }  
    157.   
    158.     }  
    159.   
    160.     /** 
    161.      * 文件解压缩 
    162.      *  
    163.      * @param destFile 
    164.      *            目标文件 
    165.      * @param zis 
    166.      *            ZipInputStream 
    167.      * @throws Exception 
    168.      */  
    169.     private static void decompressFile(File destFile, ZipInputStream zis)  
    170.             throws Exception {  
    171.   
    172.         BufferedOutputStream bos = new BufferedOutputStream(  
    173.                 new FileOutputStream(destFile));  
    174.   
    175.         int count;  
    176.         byte data[] = new byte[BUFFER];  
    177.         while ((count = zis.read(data, 0, BUFFER)) != -1) {  
    178.             bos.write(data, 0, count);  
    179.         }  
    180.   
    181.         bos.close();  
    182.     }  
    183.   
    184. }  





    其实,理解了ZIP的工作原理,这些代码看起来很好懂!

    把刚才做的压缩文件再用上述代码解开看看,测试用例如下:

    Java代码  收藏代码
    1. /** 
    2.  * 2010-4-12 
    3.  */  
    4. package org.zlex.commons.io;  
    5.   
    6. import static org.junit.Assert.*;  
    7.   
    8. import org.junit.Test;  
    9.   
    10. /** 
    11.  *  
    12.  * @author 梁栋 
    13.  * @version 1.0 
    14.  * @since 1.0 
    15.  */  
    16. public class ZipUtilsTest {  
    17.   
    18.     /** 
    19.      *   
    20.      */  
    21.     @Test  
    22.     public void test() throws Exception {  
    23.         // 解压到指定目录  
    24.         ZipUtils.decompress("d:\f.txt.zip", "d:\ff");  
    25.         // 解压到当前目录  
    26.         ZipUtils.decompress("d:\fd.zip");  
    27.     }  
    28.   
    29. }  



    完整代码详见附件!

    java原生的ZIP实现虽然在压缩时会因与系统字符集不符产生中文乱码,但在解压缩后,字符集即可恢复。

    除了java原生的ZIP实现外,commons和ant也提供了相应的ZIP算法实现,有机会我再一一介绍!

  • 相关阅读:
    论文阅读笔记(四)【TIP2017】:Video-Based Pedestrian Re-Identification by Adaptive Spatio-Temporal Appearance Model
    论文阅读目录
    【学习】从.txt文件读取生成编译代码。
    页面显示其他电脑图片(局域网)
    控制台爬取小说(大王饶命)
    【自学】大话设计模式控制台
    将PDF转化为wrod
    【学习】爬糗事百科,可自动翻页。
    AHP(使用于某项目设备重要度评估测试)
    【学习】类重构、通用值交换、释放内存计算时间等
  • 原文地址:https://www.cnblogs.com/jqmtony/p/5575111.html
Copyright © 2011-2022 走看看