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自行實現
}