學習Java壓縮技術 BZIP2

http://www.java3z.com/cwbwebhome/article/article8/81131.html

 

BZip2與GZip有什麼淵源,我這裏不深究。我要說的只是,這兩種算法,你在linux下都可以找到相應的操作命令。

GZip
壓縮
gzip <file> 將得到壓縮文件<file>.gz,同時刪除文件<file>
解壓縮
gzip -d <file>.gz 將得到壓縮文件<file>,同時刪除文件<file>.gz

BZip2與之相當,幾乎沒有什麼差別~~
BZip2
壓縮
bzip2 <file> 將得到壓縮文件<file>.bz2,同時刪除文件<file>
解壓縮
bzip2 -d <file>.bz2 將得到壓縮文件<file>,同時刪除文件<file>.bz2

除了命令不同外,幾乎是一樣的!

再說實現。GZIP是JDK自帶的算法實現,但BZip2則不曾享受這個待遇。 不過,強大的Apache堅決不會讓這些個在Linux下如魚得水的算法在Java世界中銷聲匿跡。Apache在Commons Compress中提供了相應的實現。同時,還包括衆所周知的tar、cpio、zip等算法實現,其中最爲豐富的當屬zip實現了!

我繼續依葫蘆畫瓢~~~
BZip2CompressorOutputStream類用於壓縮
BZip2CompressorInputStream類用於解壓縮


先說壓縮實現,BZip2CompressorOutputStream只有一個方法用於壓縮,就是帶定長的write方法。簡單調用如下文所示:

	/**
	 * 數據壓縮
	 * 
	 * @param is
	 * @param os
	 * @throws Exception
	 */
	public static void compress(InputStream is, OutputStream os)
			throws Exception {
		BZip2CompressorOutputStream gos = new BZip2CompressorOutputStream(os);
		int count;
		byte data[] = new byte[BUFFER];
		while ((count = is.read(data, 0, BUFFER)) != -1) {
			gos.write(data, 0, count);
		}
		gos.finish();
		gos.flush();
		gos.close();
	}


與GZip實現有何差別?除了換掉了GZIPOutputStream沒有任何差別。

解壓縮就更不用說了,BZip2CompressorInputStream提供了一個帶定長的read方法。簡單調用如下文所示:

	/**
	 * 數據解壓縮
	 * 
	 * @param is
	 * @param os
	 * @throws Exception
	 */
	public static void decompress(InputStream is, OutputStream os)
			throws Exception {
		BZip2CompressorInputStream gis = new BZip2CompressorInputStream(is);
		int count;
		byte data[] = new byte[BUFFER];
		while ((count = gis.read(data, 0, BUFFER)) != -1) {
			os.write(data, 0, count);
		}
		gis.close();
	}

嗯,沒什麼難度!
IT這行就是這樣,只要你肯用心,能觸類旁通,就能融會貫通!
給一個完整實現:

/**
 * 2010-4-15
 */
package org.zlex.commons.compress.compress;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import org.apache.commons.compress.compressors.bzip2.BZip2CompressorInputStream;
import org.apache.commons.compress.compressors.bzip2.BZip2CompressorOutputStream;
/**
 * BZip2工具
 * 
 * @author  <a href="mailto:[email protected]">樑棟</a>
 * @since 1.0
 */
public abstract class BZip2Utils {
	public static final int BUFFER = 1024;
	public static final CharSequence EXT = ".bz2";
	/**
	 * 數據壓縮
	 * 
	 * @param data
	 * @return
	 * @throws Exception
	 */
	public static byte[] compress(byte[] data) throws Exception {
		ByteArrayInputStream bais = new ByteArrayInputStream(data);
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		// 壓縮
		compress(bais, baos);
		byte[] output = baos.toByteArray();
		baos.flush();
		baos.close();
		bais.close();
		return output;
	}
	/**
	 * 文件壓縮
	 * 
	 * @param file
	 * @throws Exception
	 */
	public static void compress(File file) throws Exception {
		compress(file, true);
	}
	/**
	 * 文件壓縮
	 * 
	 * @param file
	 * @param delete
	 *            是否刪除原始文件
	 * @throws Exception
	 */
	public static void compress(File file, boolean delete) throws Exception {
		FileInputStream fis = new FileInputStream(file);
		FileOutputStream fos = new FileOutputStream(file.getPath() + EXT);
		compress(fis, fos);
		fis.close();
		fos.flush();
		fos.close();
		if (delete) {
			file.delete();
		}
	}
	/**
	 * 數據壓縮
	 * 
	 * @param is
	 * @param os
	 * @throws Exception
	 */
	public static void compress(InputStream is, OutputStream os)
			throws Exception {
		BZip2CompressorOutputStream gos = new BZip2CompressorOutputStream(os);
		int count;
		byte data[] = new byte[BUFFER];
		while ((count = is.read(data, 0, BUFFER)) != -1) {
			gos.write(data, 0, count);
		}
		gos.finish();
		gos.flush();
		gos.close();
	}
	/**
	 * 文件壓縮
	 * 
	 * @param path
	 * @throws Exception
	 */
	public static void compress(String path) throws Exception {
		compress(path, true);
	}
	/**
	 * 文件壓縮
	 * 
	 * @param path
	 * @param delete
	 *            是否刪除原始文件
	 * @throws Exception
	 */
	public static void compress(String path, boolean delete) throws Exception {
		File file = new File(path);
		compress(file, delete);
	}
	/**
	 * 數據解壓縮
	 * 
	 * @param data
	 * @return
	 * @throws Exception
	 */
	public static byte[] decompress(byte[] data) throws Exception {
		ByteArrayInputStream bais = new ByteArrayInputStream(data);
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		// 解壓縮
		decompress(bais, baos);
		data = baos.toByteArray();
		baos.flush();
		baos.close();
		bais.close();
		return data;
	}
	/**
	 * 文件解壓縮
	 * 
	 * @param file
	 * @throws Exception
	 */
	public static void decompress(File file) throws Exception {
		decompress(file, true);
	}
	/**
	 * 文件解壓縮
	 * 
	 * @param file
	 * @param delete
	 *            是否刪除原始文件
	 * @throws Exception
	 */
	public static void decompress(File file, boolean delete) throws Exception {
		FileInputStream fis = new FileInputStream(file);
		FileOutputStream fos = new FileOutputStream(file.getPath().replace(EXT,
				""));
		decompress(fis, fos);
		fis.close();
		fos.flush();
		fos.close();
		if (delete) {
			file.delete();
		}
	}
	/**
	 * 數據解壓縮
	 * 
	 * @param is
	 * @param os
	 * @throws Exception
	 */
	public static void decompress(InputStream is, OutputStream os)
			throws Exception {
		BZip2CompressorInputStream gis = new BZip2CompressorInputStream(is);
		int count;
		byte data[] = new byte[BUFFER];
		while ((count = gis.read(data, 0, BUFFER)) != -1) {
			os.write(data, 0, count);
		}
		gis.close();
	}
	/**
	 * 文件解壓縮
	 * 
	 * @param path
	 * @throws Exception
	 */
	public static void decompress(String path) throws Exception {
		decompress(path, true);
	}
	/**
	 * 文件解壓縮
	 * 
	 * @param path
	 * @param delete
	 *            是否刪除原始文件
	 * @throws Exception
	 */
	public static void decompress(String path, boolean delete) throws Exception {
		File file = new File(path);
		decompress(file, delete);
	}
}


對應再來個測試用例,測試用例如下所示:

/**
 * 2010-4-13
 */
package org.zlex.commons.compress.compress;
import static org.junit.Assert.assertEquals;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import org.junit.Test;
/**
 * BZip2
 * 
 * @author <a href="mailto:[email protected]">樑棟</a>
 * @since 1.0
 */
public class BZip2UtilsTest {
	private String inputStr = "[email protected],[email protected],[email protected],[email protected],
[email protected],[email protected],[email protected],[email protected],[email protected],
[email protected],[email protected],[email protected],[email protected],[email protected],
[email protected],[email protected],[email protected],[email protected],[email protected],
[email protected],[email protected],[email protected],[email protected],zlex.snowolf@zlex.
org,[email protected],[email protected],[email protected],[email protected],
[email protected],[email protected]";
@Testpublic final void testDataCompress() throws Exception {byte[] input = inputStr.getBytes();System.err.println("原文:\t" + inputStr);System.err.println("長度:\t" + input.length);byte[] data = BZip2Utils.compress(input);System.err.println("壓縮後:\t");System.err.println("長度:\t" + data.length);byte[] output = BZip2Utils.decompress(data);String outputStr = new String(output);System.err.println("解壓縮後:\t" + outputStr);System.err.println("長度:\t" + output.length);assertEquals(inputStr, outputStr);}@Testpublic final void testFileCompress() throws Exception {FileOutputStream fos = new FileOutputStream("d:/f.txt");fos.write(inputStr.getBytes());fos.flush();fos.close();BZip2Utils.compress("d:/f.txt");BZip2Utils.decompress("d:/f.txt.bz2");File file = new File("d:/f.txt");FileInputStream fis = new FileInputStream(file);DataInputStream dis = new DataInputStream(fis);byte[] data = new byte[(int) file.length()];dis.readFully(data);fis.close();String outputStr = new String(data);assertEquals(inputStr, outputStr);}}


雖然,兩種算法在代碼實現上幾乎沒有什麼差別,但在壓縮上想要看到效果,還真讓我費了點事!
控制檯輸出(略)


GZIP本身不需要太長的內容,經過壓縮就能體現出壓縮效果,而BZip2則需要壓縮很長的內容時,才能體現其壓縮效果,這說明BZip2更適合大數據壓縮?!

 

發佈了6 篇原創文章 · 獲贊 2 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章