Java压缩技术(四) GZIP——Java原生实现

来源:互联网 发布:c4dr18 win mac 编辑:程序博客网 时间:2024/04/30 04:20

Java压缩技术(四) GZIP——Java原生实现

    博客分类:
  • Java/Compression
JavaIEOSXMLEXT
趁着头脑清楚,抓紧时间继续整理!
熟悉linux的朋友可能都用过文件压缩命令,譬如最为简单的gzip命令。

相关链接:
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等)的实现,有机会我将继续整理!

原创粉丝点击