Java压缩技术(六) BZIP2——Commons实现

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方法。简单调用如下文所示: 
Java代码   收藏代码
  1. /** 
  2.  * 数据压缩 
  3.  *  
  4.  * @param is 
  5.  * @param os 
  6.  * @throws Exception 
  7.  */  
  8. public static void compress(InputStream is, OutputStream os)  
  9.         throws Exception {  
  10.   
  11.     BZip2CompressorOutputStream gos = new BZip2CompressorOutputStream(os);  
  12.   
  13.     int count;  
  14.     byte data[] = new byte[BUFFER];  
  15.     while ((count = is.read(data, 0, BUFFER)) != -1) {  
  16.         gos.write(data, 0, count);  
  17.     }  
  18.   
  19.     gos.finish();  
  20.   
  21.     gos.flush();  
  22.     gos.close();  
  23. }  

与GZip实现有何差别?除了换掉了GZIPOutputStream没有任何差别。  

解压缩就更不用说了,BZip2CompressorInputStream提供了一个带定长的read方法。简单调用如下文所示: 
Java代码   收藏代码
  1. /** 
  2.  * 数据解压缩 
  3.  *  
  4.  * @param is 
  5.  * @param os 
  6.  * @throws Exception 
  7.  */  
  8. public static void decompress(InputStream is, OutputStream os)  
  9.         throws Exception {  
  10.   
  11.     BZip2CompressorInputStream gis = new BZip2CompressorInputStream(is);  
  12.   
  13.     int count;  
  14.     byte data[] = new byte[BUFFER];  
  15.     while ((count = gis.read(data, 0, BUFFER)) != -1) {  
  16.         os.write(data, 0, count);  
  17.     }  
  18.   
  19.     gis.close();  
  20. }  

嗯,没什么难度!  
IT这行就是这样,只要你肯用心,能触类旁通,就能融会贯通!  
给一个完整实现: 
Java代码   收藏代码
  1. /** 
  2.  * 2010-4-15 
  3.  */  
  4. package org.zlex.commons.compress.compress;  
  5.   
  6. import java.io.ByteArrayInputStream;  
  7. import java.io.ByteArrayOutputStream;  
  8. import java.io.File;  
  9. import java.io.FileInputStream;  
  10. import java.io.FileOutputStream;  
  11. import java.io.InputStream;  
  12. import java.io.OutputStream;  
  13.   
  14. import org.apache.commons.compress.compressors.bzip2.BZip2CompressorInputStream;  
  15. import org.apache.commons.compress.compressors.bzip2.BZip2CompressorOutputStream;  
  16.   
  17. /** 
  18.  * BZip2工具 
  19.  *  
  20.  * @author  <a href="mailto:[email protected]">梁栋</a> 
  21.  * @since 1.0 
  22.  */  
  23. public abstract class BZip2Utils {  
  24.   
  25.     public static final int BUFFER = 1024;  
  26.     public static final CharSequence EXT = ".bz2";  
  27.   
  28.     /** 
  29.      * 数据压缩 
  30.      *  
  31.      * @param data 
  32.      * @return 
  33.      * @throws Exception 
  34.      */  
  35.     public static byte[] compress(byte[] data) throws Exception {  
  36.         ByteArrayInputStream bais = new ByteArrayInputStream(data);  
  37.         ByteArrayOutputStream baos = new ByteArrayOutputStream();  
  38.   
  39.         // 压缩  
  40.         compress(bais, baos);  
  41.   
  42.         byte[] output = baos.toByteArray();  
  43.   
  44.         baos.flush();  
  45.         baos.close();  
  46.   
  47.         bais.close();  
  48.   
  49.         return output;  
  50.     }  
  51.   
  52.     /** 
  53.      * 文件压缩 
  54.      *  
  55.      * @param file 
  56.      * @throws Exception 
  57.      */  
  58.     public static void compress(File file) throws Exception {  
  59.         compress(file, true);  
  60.     }  
  61.   
  62.     /** 
  63.      * 文件压缩 
  64.      *  
  65.      * @param file 
  66.      * @param delete 
  67.      *            是否删除原始文件 
  68.      * @throws Exception 
  69.      */  
  70.     public static void compress(File file, boolean delete) throws Exception {  
  71.         FileInputStream fis = new FileInputStream(file);  
  72.         FileOutputStream fos = new FileOutputStream(file.getPath() + EXT);  
  73.   
  74.         compress(fis, fos);  
  75.   
  76.         fis.close();  
  77.         fos.flush();  
  78.         fos.close();  
  79.   
  80.         if (delete) {  
  81.             file.delete();  
  82.         }  
  83.     }  
  84.   
  85.     /** 
  86.      * 数据压缩 
  87.      *  
  88.      * @param is 
  89.      * @param os 
  90.      * @throws Exception 
  91.      */  
  92.     public static void compress(InputStream is, OutputStream os)  
  93.             throws Exception {  
  94.   
  95.         BZip2CompressorOutputStream gos = new BZip2CompressorOutputStream(os);  
  96.   
  97.         int count;  
  98.         byte data[] = new byte[BUFFER];  
  99.         while ((count = is.read(data, 0, BUFFER)) != -1) {  
  100.             gos.write(data, 0, count);  
  101.         }  
  102.   
  103.         gos.finish();  
  104.   
  105.         gos.flush();  
  106.         gos.close();  
  107.     }  
  108.   
  109.     /** 
  110.      * 文件压缩 
  111.      *  
  112.      * @param path 
  113.      * @throws Exception 
  114.      */  
  115.     public static void compress(String path) throws Exception {  
  116.         compress(path, true);  
  117.     }  
  118.   
  119.     /** 
  120.      * 文件压缩 
  121.      *  
  122.      * @param path 
  123.      * @param delete 
  124.      *            是否删除原始文件 
  125.      * @throws Exception 
  126.      */  
  127.     public static void compress(String path, boolean delete) throws Exception {  
  128.         File file = new File(path);  
  129.         compress(file, delete);  
  130.     }  
  131.   
  132.     /** 
  133.      * 数据解压缩 
  134.      *  
  135.      * @param data 
  136.      * @return 
  137.      * @throws Exception 
  138.      */  
  139.     public static byte[] decompress(byte[] data) throws Exception {  
  140.         ByteArrayInputStream bais = new ByteArrayInputStream(data);  
  141.         ByteArrayOutputStream baos = new ByteArrayOutputStream();  
  142.   
  143.         // 解压缩  
  144.   
  145.         decompress(bais, baos);  
  146.   
  147.         data = baos.toByteArray();  
  148.   
  149.         baos.flush();  
  150.         baos.close();  
  151.   
  152.         bais.close();  
  153.   
  154.         return data;  
  155.     }  
  156.   
  157.     /** 
  158.      * 文件解压缩 
  159.      *  
  160.      * @param file 
  161.      * @throws Exception 
  162.      */  
  163.     public static void decompress(File file) throws Exception {  
  164.         decompress(file, true);  
  165.     }  
  166.   
  167.     /** 
  168.      * 文件解压缩 
  169.      *  
  170.      * @param file 
  171.      * @param delete 
  172.      *            是否删除原始文件 
  173.      * @throws Exception 
  174.      */  
  175.     public static void decompress(File file, boolean delete) throws Exception {  
  176.         FileInputStream fis = new FileInputStream(file);  
  177.         FileOutputStream fos = new FileOutputStream(file.getPath().replace(EXT,  
  178.                 ""));  
  179.         decompress(fis, fos);  
  180.         fis.close();  
  181.         fos.flush();  
  182.         fos.close();  
  183.   
  184.         if (delete) {  
  185.             file.delete();  
  186.         }  
  187.     }  
  188.   
  189.     /** 
  190.      * 数据解压缩 
  191.      *  
  192.      * @param is 
  193.      * @param os 
  194.      * @throws Exception 
  195.      */  
  196.     public static void decompress(InputStream is, OutputStream os)  
  197.             throws Exception {  
  198.   
  199.         BZip2CompressorInputStream gis = new BZip2CompressorInputStream(is);  
  200.   
  201.         int count;  
  202.         byte data[] = new byte[BUFFER];  
  203.         while ((count = gis.read(data, 0, BUFFER)) != -1) {  
  204.             os.write(data, 0, count);  
  205.         }  
  206.   
  207.         gis.close();  
  208.     }  
  209.   
  210.     /** 
  211.      * 文件解压缩 
  212.      *  
  213.      * @param path 
  214.      * @throws Exception 
  215.      */  
  216.     public static void decompress(String path) throws Exception {  
  217.         decompress(path, true);  
  218.     }  
  219.   
  220.     /** 
  221.      * 文件解压缩 
  222.      *  
  223.      * @param path 
  224.      * @param delete 
  225.      *            是否删除原始文件 
  226.      * @throws Exception 
  227.      */  
  228.     public static void decompress(String path, boolean delete) throws Exception {  
  229.         File file = new File(path);  
  230.         decompress(file, delete);  
  231.     }  
  232.   
  233. }  

对应再来个测试用例,测试用例如下所示: 
Java代码   收藏代码
  1. /** 
  2.  * 2010-4-13 
  3.  */  
  4. package org.zlex.commons.compress.compress;  
  5.   
  6. import static org.junit.Assert.assertEquals;  
  7.   
  8. import java.io.DataInputStream;  
  9. import java.io.File;  
  10. import java.io.FileInputStream;  
  11. import java.io.FileOutputStream;  
  12.   
  13. import org.junit.Test;  
  14.   
  15. /** 
  16.  * BZip2 
  17.  *  
  18.  * @author <a href="mailto:[email protected]">梁栋</a> 
  19.  * @since 1.0 
  20.  */  
  21. public class BZip2UtilsTest {  
  22.   
  23.     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],[email protected],[email protected],[email protected],[email protected],[email protected],[email protected],[email protected]";  
  24.   
  25.     @Test  
  26.     public final void testDataCompress() throws Exception {  
  27.   
  28.         byte[] input = inputStr.getBytes();  
  29.         System.err.println("原文:\t" + inputStr);  
  30.         System.err.println("长度:\t" + input.length);  
  31.   
  32.         byte[] data = BZip2Utils.compress(input);  
  33.         System.err.println("压缩后:\t");  
  34.         System.err.println("长度:\t" + data.length);  
  35.   
  36.         byte[] output = BZip2Utils.decompress(data);  
  37.         String outputStr = new String(output);  
  38.         System.err.println("解压缩后:\t" + outputStr);  
  39.         System.err.println("长度:\t" + output.length);  
  40.   
  41.         assertEquals(inputStr, outputStr);  
  42.   
  43.     }  
  44.   
  45.     @Test  
  46.     public final void testFileCompress() throws Exception {  
  47.   
  48.         FileOutputStream fos = new FileOutputStream("d:/f.txt");  
  49.   
  50.         fos.write(inputStr.getBytes());  
  51.         fos.flush();  
  52.         fos.close();  
  53.   
  54.         BZip2Utils.compress("d:/f.txt");  
  55.   
  56.         BZip2Utils.decompress("d:/f.txt.bz2");  
  57.   
  58.         File file = new File("d:/f.txt");  
  59.   
  60.         FileInputStream fis = new FileInputStream(file);  
  61.   
  62.         DataInputStream dis = new DataInputStream(fis);  
  63.   
  64.         byte[] data = new byte[(int) file.length()];  
  65.         dis.readFully(data);  
  66.   
  67.         fis.close();  
  68.   
  69.         String outputStr = new String(data);  
  70.         assertEquals(inputStr, outputStr);  
  71.     }  
  72. }  

虽然,两种算法在代码实现上几乎没有什么差别,但在压缩上想要看到效果,还真让我费了点事!  
控制台输出如下所示: 
引用

529字节-->76字节! 
GZIP本身不需要太长的内容,经过压缩就能体现出压缩效果,而BZip2则需要压缩很长的内容时,才能体现其压缩效果,这说明BZip2更适合大数据压缩?!  

Commons Compress不仅支持BZip2算法实现,同时也支持GZip算法实现。对于GZip算法实现,与Java原生实现基本上没有什么差别。其源代码分析,仅仅是做了简单的包装。 
不过有必要提及的一点是,Commons Compress为压缩(GZip和BZip2)构建了压缩算法工厂类 CompressorStreamFactory 。通过这个类可以方便的构建GZip和BZip2的输入输出流,关键字分别为“gz”和“bzip2”。 
GZip 
Java代码   收藏代码
  1. // GzipCompressorInputStream        
  2. CompressorInputStream gzipIn = new CompressorStreamFactory()  
  3.         .createCompressorInputStream("gz", is);  
  4.   
  5. // GzipCompressorOutputStream  
  6. CompressorOutputStream gzipOut = new CompressorStreamFactory()  
  7.         .createCompressorOutputStream("gz", os);  

BZip2 
Java代码   收藏代码
  1. // BZip2CompressorInputStream  
  2. CompressorInputStream bzip2In = new CompressorStreamFactory()  
  3.         .createCompressorInputStream("bzip2", is);  
  4.   
  5. // BZip2CompressorOutputStream  
  6. CompressorOutputStream bzip2Out = new CompressorStreamFactory()  
  7.         .createCompressorOutputStream("bzip2", os);  

GZip和BZip2在算法实现步骤上基本上没有什么差别,如果有必要统一,可按上述代码实现!  

你可能感兴趣的:(java,压缩,技术)