Java压缩技术

趁着头脑清楚,抓紧时间继续整理!
熟悉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.     GZIPOutputStream gos = new GZIPOutputStream(os);
  11.     int count;
  12.     byte data[] = new byte[BUFFER];
  13.     while ((count = is.read(data, 0, BUFFER)) != -1) {
  14.         gos.write(data, 0, count);
  15.     }
  16.     gos.finish();
  17.     gos.flush();
  18.     gos.close();
  19. }

记得完成操作后,调用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.     GZIPInputStream gis = new GZIPInputStream(is);
  11.     int count;
  12.     byte data[] = new byte[BUFFER];
  13.     while ((count = gis.read(data, 0, BUFFER)) != -1) {
  14.         os.write(data, 0, count);
  15.     }
  16.     gis.close();
  17. }

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

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

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

Java代码  收藏代码
  1. /**
  2.  * 2010-4-13
  3.  */
  4. package org.zlex.commons.compress.compress;
  5. import static org.junit.Assert.assertEquals;
  6. import java.io.DataInputStream;
  7. import java.io.File;
  8. import java.io.FileInputStream;
  9. import java.io.FileOutputStream;
  10. import org.junit.Test;
  11. /**
  12.  * @author <a href="mailto:zlex.dongliang@gmail.com">梁栋</a>
  13.  * @since 1.0
  14.  */
  15. public class GZipUtilsTest {
  16.     private String inputStr = "zlex@zlex.org,snowolf@zlex.org,zlex.snowolf@zlex.org";
  17.     @Test
  18.     public final void testDataCompress() throws Exception {
  19.         System.err.println("原文:\t" + inputStr);
  20.         byte[] input = inputStr.getBytes();
  21.         System.err.println("长度:\t" + input.length);
  22.         byte[] data = GZipUtils.compress(input);
  23.         System.err.println("压缩后:\t");
  24.         System.err.println("长度:\t" + data.length);
  25.         byte[] output = GZipUtils.decompress(data);
  26.         String outputStr = new String(output);
  27.         System.err.println("解压缩后:\t" + outputStr);
  28.         System.err.println("长度:\t" + output.length);
  29.         assertEquals(inputStr, outputStr);
  30.     }
  31.     @Test
  32.     public final void testFileCompress() throws Exception {
  33.         FileOutputStream fos = new FileOutputStream("d:/f.txt");
  34.         fos.write(inputStr.getBytes());
  35.         fos.flush();
  36.         fos.close();
  37.         GZipUtils.compress("d:/f.txt", false);
  38.         GZipUtils.decompress("d:/f.txt.gz", false);
  39.         File file = new File("d:/f.txt");
  40.         FileInputStream fis = new FileInputStream(file);
  41.         DataInputStream dis = new DataInputStream(fis);
  42.         byte[] data = new byte[(int) file.length()];
  43.         dis.readFully(data);
  44.         fis.close();
  45.         String outputStr = new String(data);
  46.         assertEquals(inputStr, outputStr);
  47.     }
  48. }

结果如何?
先看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实现

gzip.rar

http://snowolf.iteye.com/blog/643010

  1. da shang
    donate-alipay
               donate-weixin weixinpay

发表评论↓↓