Java压缩技术(二) ZIP压缩——Java原生实现
去年整理了一篇ZLib算法Java实现(Java压缩技术(一) ZLib),一直惦记却没时间补充。今天得空,整理一下ZIP的java原生实现。看了几篇zip压缩算法的帖子,讲的算是比较细致了,但就是没有对应的解压缩实现,太惜败了!http://www.agoit.com/images/smiles/icon_sad.gif 我就喜欢没事做总结,稍作整理,将其收纳!http://www.agoit.com/images/smiles/icon_biggrin.gif
相关链接:
Java压缩技术(一) ZLib
Java压缩技术(二) ZIP压缩——Java原生实现
Java压缩技术(三) ZIP解压缩——Java原生实现
Java压缩技术(四) GZIP——Java原生实现
Java压缩技术(五) GZIP相关——浏览器解析
Java压缩技术(六) BZIP2——Commons实现
Java压缩技术(七) TAR——Commons实现
查过相关资料后才知道,ZIP应该算作归档类的压缩算法,每一门学科都可深可浅!http://www.agoit.com/images/smiles/icon_biggrin.gif
闲言少叙,先说ZIP压缩。
zip压缩需要通过ZipOutputStream 执行write方法将压缩数据写到指定输出流中。
注意,这里应先使用CheckedOutputStream 指定文件校验算法。(通常使用CRC32算法)。代码如下所示:
CheckedOutputStream cos = new CheckedOutputStream(new FileOutputStream(destPath), new CRC32());ZipOutputStream zos = new ZipOutputStream(cos);
接下来,需要将待压缩文件以ZipEntry的方式追加到压缩文件中,如下所示:
/** * 压缩包内文件名定义 ** <pre> * 如果有多级目录,那么这里就需要给出包含目录的文件名 * 如果用WinRAR打开压缩包,中文名将显示为乱码 * </pre> */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;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);}}
x是一个空目录,用WinRAR打开后,可以看到这个目录下还有一个空文件名文件!http://www.agoit.com/images/smiles/icon_surprised.gif
http://dl.iteye.com/upload/attachment/237198/e666b02f-3529-3c26-9b7a-d997fd330414.jpg
来个完整的压缩实现,代码如下所示:
/** * 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;while ((count = bis.read(data, 0, BUFFER)) != -1) {zos.write(data, 0, count);}bis.close();zos.closeEntry();}}
来做个简单的测试:
import static org.junit.Assert.*;import org.junit.Test;/** ** @author 梁栋 * @version 1.0 * @since 1.0 */public class ZipUtilsTest {/** * */@Testpublic void test() throws Exception {// 压缩文件ZipUtils.compress("d:\\f.txt");// 压缩目录ZipUtils.compress("d:\\fd");}}
现在用WinRAR打开看看,是不是效果几乎一致?http://www.agoit.com/images/smiles/icon_biggrin.gif
当然,上述代码有所不足之处主要是中文名称乱码问题。用java原生ZIP实现压缩后得到的压缩包,与系统的字符集不同,文件/目录名将出现乱码。这是所有归档压缩都会遇到的问题。对于这种问题,Commons Copress提供了解决方案!http://www.agoit.com/images/smiles/icon_biggrin.gif
对于解压缩,请关注后续内容!http://www.agoit.com/images/smiles/icon_biggrin.gif
相关链接:
Java压缩技术(一) ZLib
Java压缩技术(二) ZIP压缩——Java原生实现
Java压缩技术(三) ZIP解压缩——Java原生实现
Java压缩技术(四) GZIP——Java原生实现
Java压缩技术(五) GZIP相关——浏览器解析
Java压缩技术(六) BZIP2——Commons实现
Java压缩技术(七) TAR——Commons实现
页:
[1]