java zip 压缩的学习

参考: http://snowolf.iteye.com/blog/642298  

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

  ZIP应该算作归档类的压缩算法

zip压缩需要通过ZipOutputStream 执行write方法将压缩数据写到指定输出流中。 

注意,这里应先使用CheckedOutputStream 指定文件校验算法。(通常使用CRC32算法)。代码如下所示:

CheckedOutputStream cos = new CheckedOutputStream(new FileOutputStream(destPath), new CRC32());  
ZipOutputStream zos = new ZipOutputStream(cos);  

接下来,需要将待压缩文件以ZipEntry的方式追加到压缩文件中,如下所示: 

/** 
 * 压缩包内文件名定义 
 *  
 * 如果有多级目录,那么这里就需要给出包含目录的文件名 
 * 如果用WinRAR打开压缩包,中文名将显示为乱码 
 * 
 */  
ZipEntry entry = new ZipEntry(dir + file.getName());  
  
zos.putNextEntry(entry);  

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();  
当然,如果待添加的压缩项是一个目录。那么,需要通过递归的方式指定最终的压缩项。 
如果要添加一个空目录,注意使用符号"/"(String PATH="/";)作为添加项名字结尾符!  

递归构建目录压缩,代码如下: 

/** 
 * 压缩 
 *  
 * @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 {  
  
    File[] files = dir.listFiles();  
  
    // 构建空目录  
    if (files.length < 1) {  
        ZipEntry entry = new ZipEntry(basePath + dir.getName() + PATH);  
  
        zos.putNextEntry(entry);  
        zos.closeEntry();  
    }  
  
    for (File file : files) {  
        // 递归压缩  
        compress(file, zos, basePath + dir.getName() + PATH);  
    }  
}  

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

/** 
 * 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 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.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 srcPath 
     * @throws Exception 
     */  
    public static void compress(String srcPath) throws Exception {  
        File srcFile = new File(srcPath);  
  
        compress(srcFile);  
    }  
  
    /** 
     * 文件压缩 
     *  
     * @param srcPath 
     *            源文件路径 
     * @param destPath 
     *            目标文件路径 
     *  
     */  
    public static void compress(String srcPath, String destPath)  
            throws Exception {  
        File srcFile = new File(srcPath);  
  
        compress(srcFile, destPath);  
    }  
  
    /** 
     * 压缩目录 
     *  
     * @param dir 
     * @param zos 
     * @param basePath 
     * @throws Exception 
     */  
    private static void compressDir(File dir, ZipOutputStream zos,  
            String basePath) throws Exception {  
  
        File[] files = dir.listFiles();  
  
        // 构建空目录  
        if (files.length < 1) {  
            ZipEntry entry = new ZipEntry(basePath + dir.getName() + PATH);  
  
            zos.putNextEntry(entry);  
            zos.closeEntry();  
        }  
  
        for (File file : files) {  
  
            // 递归压缩  
            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();  
  
        zos.closeEntry();  
    }  
  
}  

当然,上述代码有所不足之处主要是中文名称乱码问题。用java原生ZIP实现压缩后得到的压缩包,与系统的字符集不同,文件/目录名将出现乱码。这是所有归档压缩都会遇到的问题。对于这种问题,Commons Copress提供了解决方案!

这里说到了中文名称乱码的问题,实际测试 没发现该问题。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值