Java解压缩技术的实现 GZIP ZIP BZIP2系列实现
没啥好说的,都是些文件操作,直接贴代码
package com.ljh.zip;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
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;
/**
* @Desc: ZIP 压缩工具(文件压缩建议使用,支持文件夹解压缩)
* ZIP可用于socket套接字流数据压缩(实现方式类似)
* @author ljh
* @date 2015-4-14 上午9:39:14
*/
public class ZipUtils {
private static final int BUFFER = 1024;
private static final String EXT = ".zip";
private static final String BASE_DIR = "";
private static final String PATH = "/"; // 符号"/"用来作为ZIP压缩文件内部的目录标识判断符[因为ZipEntry.isDirectory()方法内部是以'/'来作为目录标识符的]
/**
* @Description: ZIP 数据压缩
* @author (ljh) @date 2015-4-13 下午6:00:52
* @param data
* @return
* @throws IOException
* @return byte[]
*/
public static byte[] compressData(byte[] data) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ZipOutputStream zipOS = new ZipOutputStream(baos);
ZipEntry entry = new ZipEntry("zip");
entry.setSize(data.length);
zipOS.putNextEntry(entry);
zipOS.write(data);
zipOS.closeEntry();
zipOS.close();
baos.close();
return baos.toByteArray();
}
/**
* @Description: ZIP 数据解压缩
* @author (ljh) @date 2015-4-13 下午6:00:42
* @param bytes
* @return
* @throws IOException
* @return byte[]
*/
public static byte[] uncompressData(byte[] data) throws IOException {
ByteArrayInputStream bais = new ByteArrayInputStream(data);
ZipInputStream zipIS = new ZipInputStream(bais);
byte[] bytes = null;
while (zipIS.getNextEntry() != null) {
byte[] buf = new byte[BUFFER];
int count;
ByteArrayOutputStream baos = new ByteArrayOutputStream(BUFFER);
while ((count = zipIS.read(buf, 0, buf.length)) != -1) {
baos.write(buf, 0, count);
}
bytes = baos.toByteArray();
baos.flush();
baos.close();
}
zipIS.close();
bais.close();
return bytes;
}
/**
* @Description: 文件压缩
* @author (ljh) @date 2015-4-14 上午9:32:52
* @param path
* 源文件路径
* @throws IOException
* @return void
*/
public static void compress(String srcPath) throws IOException {
compress(new File(srcPath));
}
public static void compress(File srcFile) throws IOException {
compress(srcFile, srcFile.getPath() + EXT);
}
public static void compress(String srcPath, String destPath) throws IOException {
compress(new File(srcPath), new File(destPath));
}
public static void compress(File srcFile, String destPath) throws IOException{
compress(srcFile, new File(destPath));
}
/**
* @Description: 开始文件压缩
* @author (ljh) @date 2015-4-14 上午10:54:06
* @param srcFile
* @param destFile
* @throws IOException
* @return void
*/
public static void compress(File srcFile, File destFile) throws IOException {
CheckedOutputStream cos = new CheckedOutputStream(new FileOutputStream(destFile), new CRC32());// 对输出文件做CRC32校验
ZipOutputStream zipOS = new ZipOutputStream(cos);
compress(srcFile, zipOS, BASE_DIR);
zipOS.flush();
zipOS.close();
cos.close();
}
/**
* @Description: ZIP 文件/目录
* @author (ljh) @date 2015-4-14 下午12:41:33
* @param srcFile 源文件/目录
* @param zipOS 输出流
* @param basePath
* @throws IOException
* @return void
*/
public static void compress(File srcFile, ZipOutputStream zipOS, String basePath) throws IOException {
if (srcFile.isDirectory()) {
compressDir(srcFile, zipOS, basePath);
} else {
compressFile(srcFile, zipOS, basePath);
}
}
/**
* @Description: ZIP 文件压缩
* @author (ljh) @date 2015-4-14 上午10:36:56
* @param file
* @param zipOS
* @throws IOException
* @return void
*/
private static void compressFile(File file, ZipOutputStream zipOS, String basePath) throws IOException {
/**
* 压缩包内文件名定义 ,如果有多级目录,那么这里就需要给出包含目录的文件名 ,如果用WinRAR打开压缩包,中文名将显示为乱码
*/
ZipEntry entry = new ZipEntry(basePath + file.getName());
zipOS.putNextEntry(entry);
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
int count;
byte[] buf = new byte[BUFFER];
while ((count = bis.read(buf, 0, buf.length)) != -1) {
zipOS.write(buf, 0, count);
}
bis.close();
zipOS.closeEntry();
}
/**
* @Description: 目录压缩
* @author (ljh) @date 2015-4-14 下午12:40:49
* @param dirFile
* @param zipOS
* @param basePath
* @throws IOException
* @return void
*/
private static void compressDir(File dirFile, ZipOutputStream zipOS, String basePath) throws IOException {
File[] files = dirFile.listFiles();
// 构建空目录
if (files.length < 1) {// 空目录
ZipEntry entry = new ZipEntry(basePath + dirFile.getName() + PATH);
zipOS.putNextEntry(entry);
zipOS.closeEntry();
}
for (File file : files) {
compress(file, zipOS, basePath + dirFile.getName() + PATH); // 递归压缩
}
}
//---------------------------------------------------------------
/**
* @Description: ZIP文件解压缩
* @author (ljh) @date 2015-4-14 下午12:46:25
* @param srcPath
* @throws IOException
* @return void
*/
public static void uncompress(String srcPath) throws IOException {
uncompress(new File(srcPath));
}
public static void uncompress(File srcFile) throws IOException {
uncompress(srcFile, srcFile.getParent());
}
public static void uncompress(String srcPath, String destPath) throws IOException {
uncompress(new File(srcPath), destPath);
}
public static void uncompress(File srcFile, String destPath) throws IOException {
uncompress(srcFile, new File(destPath));
}
/**
* @Description: 开始ZIP文件解压缩
* @author (ljh) @date 2015-4-14 下午12:47:00
* @param srcFile
* @param destFile
* @throws IOException
* @return void
*/
public static void uncompress(File srcFile, File destFile) throws IOException {
CheckedInputStream cis = new CheckedInputStream(new FileInputStream(srcFile), new CRC32());
ZipInputStream zipIS = new ZipInputStream(cis);
uncompress(zipIS, destFile);
zipIS.close();
cis.close();
}
private static void uncompress(ZipInputStream zipIS, File destFile) throws IOException {
ZipEntry entry = null;
while ((entry = zipIS.getNextEntry()) != null) {
String dir = destFile.getPath() + File.separator + entry.getName();
File dirFile = new File(dir);
fileProber(dirFile);//递归创建dirFile父目录
if (entry.isDirectory()) {
dirFile.mkdirs();
} else {
uncompressFile(zipIS, dirFile);
}
zipIS.closeEntry();
}
}
/**
* @Description: 当父目录不存在时,创建目录
* @author (ljh) @date 2015-4-14 下午12:54:25
* @param dirFile
* @return void
*/
private static void fileProber(File dirFile) {
File parentFile = dirFile.getParentFile();
if (!parentFile.exists()) {
fileProber(parentFile); //递归寻找上级目录并递归创建
parentFile.mkdir();
}
}
/**
* 文件解压缩
* @throws IOException
*/
private static void uncompressFile(ZipInputStream zipIS, File destFile) throws IOException {
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(destFile));
int count;
byte buf[] = new byte[BUFFER];
while ((count = zipIS.read(buf, 0, buf.length)) != -1) {
bos.write(buf, 0, count);
}
bos.close();
}
// --------------------------------------------
}
测试方法:
/**
* @Description: 被压缩数据较大才比较明显[测试发现中文byte字节大于200的时候才有明显的压缩,英文150才明显]
* @author (ljh) @date 2015-4-14 上午11:33:13
* @throws IOException
* @return void
*/
// @org.junit.Test
private static void testZIP() throws IOException {
byte[] bytes = "啊了简单概括啦啦as了的价格了看洒落的空间关了撒娇g9w9eijgslkj是肯德基了感觉是肯德基斤斤计较斤斤计较斤斤计较斤斤计较斤斤计较斤斤计较死死死死死死死死死死死死啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦".getBytes();
// 对bytes压缩
// 验证一下压缩后的效果对比
System.out.println("压缩前:");
System.out.println(bytes.length);
for (byte b : bytes) {
System.out.print(b + " ");
}
System.out.println();
System.out.println("压缩后:");
byte[] bytes2 = ZipUtils.compressData(bytes);
System.out.println(bytes2.length);
for (byte b : bytes2) {
System.out.print(b + " ");
}
System.out.println();
System.out.println("解压缩后:");
byte[] byte22 = ZipUtils.uncompressData(bytes2);
System.out.println(byte22.length);
for (byte b : byte22) {
System.out.print(b+" ");
}
System.out.println();
// ZipUtils.compress("F:\\test\\test1");
// ZipUtils.uncompress("F:\\test\\test1.zip");
//要压缩文件夹请参考ZIPUtils自行实现
}