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自行實作
}
點我下載下傳相關源碼