昆明网站推广优化,杭州网络公司 小程序,网络传媒公司注册经营范围,属性词 关键词 核心词转载自 Java压缩技术#xff08;二#xff09; ZIP压缩——Java原生实现
查过相关资料后才知道#xff0c;ZIP应该算作归档类的压缩算法#xff0c;每一门学科都可深可浅#xff01; 闲言少叙#xff0c;先说ZIP压缩。 zip压缩需要通过ZipOutputStream 执行write方法将…转载自 Java压缩技术二 ZIP压缩——Java原生实现
查过相关资料后才知道ZIP应该算作归档类的压缩算法每一门学科都可深可浅 闲言少叙先说ZIP压缩。 zip压缩需要通过ZipOutputStream 执行write方法将压缩数据写到指定输出流中。 注意这里应先使用CheckedOutputStream 指定文件校验算法。通常使用CRC32算法。代码如下所示
Java代码CheckedOutputStream cos new CheckedOutputStream(new FileOutputStream(destPath), new CRC32()); ZipOutputStream zos new ZipOutputStream(cos); 接下来需要将待压缩文件以ZipEntry的方式追加到压缩文件中如下所示 Java代码 /** * 压缩包内文件名定义 * * pre * 如果有多级目录那么这里就需要给出包含目录的文件名 * 如果用WinRAR打开压缩包中文名将显示为乱码 * /pre */ ZipEntry entry new ZipEntry(dir file.getName()); zos.putNextEntry(entry); ZipEntry就是压缩包中的每一个实体 完成上述准备后就可以执行压缩操作了。实际上就是执行ZipOutputStream类的write方法如下所示 Java代码 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/;)作为添加项名字结尾符递归构建目录压缩代码如下 Java代码 /** * 压缩 * * 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); } } x是一个空目录用WinRAR打开后可以看到这个目录下还有一个空文件名文件来个完整的压缩实现代码如下所示 Java代码 /** * 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 hrefmailto:zlex.donglianggmail.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代码 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); } } 现在用WinRAR打开看看是不是效果几乎一致当然上述代码有所不足之处主要是中文名称乱码问题。用java原生ZIP实现压缩后得到的压缩包与系统的字符集不同文件/目录名将出现乱码。这是所有归档压缩都会遇到的问题。对于这种问题Commons Copress提供了解决方案