Java压缩技术 GZIP——Java原生实现

系统 1891 0

相关链接: 
Java压缩技术(一) ZLib  
Java压缩技术(二) ZIP压缩——Java原生实现  
Java压缩技术(三) ZIP解压缩——Java原生实现  
Java压缩技术(四) GZIP——Java原生实现  
Java压缩技术(五) GZIP相关——浏览器解析  
Java压缩技术(六) BZIP2——Commons实现  
Java压缩技术(七) TAR——Commons实现  

GZIP常常用在linxu环境下,是一种非常简单的压缩算法。在Java实现API中,它仅仅包含两个实现类:GZIPInputStream和GZIPOutputStream。 
GZIPOutputStream类用于压缩  
GZIPInputStream类用于解压缩  

先说压缩实现,GZIPOutputStream只有一个方法用于压缩,就是带定长的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.     GZIPOutputStream gos =  new  GZIPOutputStream(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. }  


记得完成操作后,调用finish方法和flush方法!  

核心的压缩实现就这么多!  

对于解压缩,GZIPInputStream也对应GZIPOutputStream提供了一个带定长的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.     GZIPInputStream gis =  new  GZIPInputStream(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. }  



就这么简单!  核心内容完毕! 

顺便补充一下,在liunx下操作gzip命令 

gzip file 用于压缩,如 gzip a.txt 将得到文件 a.txt.gz 同时删除文件a.txt!  
gzip -d file.gz 用于解压缩,如 gzip -d a.txt.gz 将得到文件 a.txt 同时删除文件a.txt.gz!  

根据这些特性,我补充了相应的文件操作实现,详见下文!  

完整实现: 

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



罗嗦了半天,到底行不行? 
来个测试用例,测试用例如下所示: 

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.  * @author <a href="mailto:zlex.dongliang@gmail.com">梁栋</a>  
  17.  * @since 1.0  
  18.  */   
  19. public   class  GZipUtilsTest {  
  20.   
  21.      private  String inputStr =  "zlex@zlex.org,snowolf@zlex.org,zlex.snowolf@zlex.org" ;  
  22.   
  23.      @Test   
  24.      public   final   void  testDataCompress()  throws  Exception {  
  25.   
  26.         System.err.println( "原文:\t"  + inputStr);  
  27.   
  28.          byte [] input = inputStr.getBytes();  
  29.         System.err.println( "长度:\t"  + input.length);  
  30.   
  31.          byte [] data = GZipUtils.compress(input);  
  32.         System.err.println( "压缩后:\t" );  
  33.         System.err.println( "长度:\t"  + data.length);  
  34.   
  35.          byte [] output = GZipUtils.decompress(data);  
  36.         String outputStr =  new  String(output);  
  37.         System.err.println( "解压缩后:\t"  + outputStr);  
  38.         System.err.println( "长度:\t"  + output.length);  
  39.   
  40.         assertEquals(inputStr, outputStr);  
  41.   
  42.     }  
  43.   
  44.      @Test   
  45.      public   final   void  testFileCompress()  throws  Exception {  
  46.   
  47.         FileOutputStream fos =  new  FileOutputStream( "d:/f.txt" );  
  48.   
  49.         fos.write(inputStr.getBytes());  
  50.         fos.flush();  
  51.         fos.close();  
  52.   
  53.         GZipUtils.compress( "d:/f.txt" false );  
  54.   
  55.         GZipUtils.decompress( "d:/f.txt.gz" false );  
  56.   
  57.         File file =  new  File( "d:/f.txt" );  
  58.   
  59.         FileInputStream fis =  new  FileInputStream(file);  
  60.   
  61.         DataInputStream dis =  new  DataInputStream(fis);  
  62.   
  63.          byte [] data =  new   byte [( int ) file.length()];  
  64.         dis.readFully(data);  
  65.   
  66.         fis.close();  
  67.   
  68.         String outputStr =  new  String(data);  
  69.         assertEquals(inputStr, outputStr);  
  70.     }  
  71. }  


结果如何? 
先看testDataCompress()方法控制台输出结果。 
控制台输出如下: 

引用

原文: zlex@zlex.org,snowolf@zlex.org,zlex.snowolf@zlex.org 
长度: 52 
压缩后:
长度: 45 
解压缩后: zlex@zlex.org,snowolf@zlex.org,zlex.snowolf@zlex.org 
长度: 52 


这里使用英文字符做测试,当输入字符串的字节数大于50左右时,压缩效果明显;如果这里使用中文压缩,可能当压缩上千字节时方能体现出压缩效果! 
对于文件操作,朋友们可以自行实验,我代码里的实现是按照gzip命令来的! 
举例来说: 
压缩时,将文件a.txt压缩为a.txt.gz,同时删除文件a.txt。 
解压缩时,将文件a.txt.gz解压缩为a.txt,同时删除文件a.txt.gz。 

注意执行testFileCompress方法,查看产生的文件!  你大可以放到linux上去做验证!  

commons也提供了GZIP算法的实现,甚至更多种压缩算法(tar、bzip2等)的实现,有机会我将继续整理!  

相关链接: 
Java压缩技术(一) ZLib  
Java压缩技术(二) ZIP压缩——Java原生实现  
Java压缩技术(三) ZIP解压缩——Java原生实现  
Java压缩技术(四) GZIP——Java原生实现  
Java压缩技术(五) GZIP相关——浏览器解析  
Java压缩技术(六) BZIP2——Commons实现  
Java压缩技术(七) TAR——Commons实现

Java压缩技术 GZIP——Java原生实现


更多文章、技术交流、商务合作、联系博主

微信扫码或搜索:z360901061

微信扫一扫加我为好友

QQ号联系: 360901061

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描下面二维码支持博主2元、5元、10元、20元等您想捐的金额吧,狠狠点击下面给点支持吧,站长非常感激您!手机微信长按不能支付解决办法:请将微信支付二维码保存到相册,切换到微信,然后点击微信右上角扫一扫功能,选择支付二维码完成支付。

【本文对您有帮助就好】

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描上面二维码支持博主2元、5元、10元、自定义金额等您想捐的金额吧,站长会非常 感谢您的哦!!!

发表我的评论
最新评论 总共0条评论