zoukankan      html  css  js  c++  java
  • java内置的解压缩工具

    简介

    java关于压缩和解压缩的核心类就是Defalter(压缩)类和Inflater(解压)类,操作GZip和Zip文件也是基于这两个类。Tomcat对响应数据的压缩就是基于GZip。

    使用Deflater和Inflater解压缩

    import java.io.BufferedInputStream;
    import java.io.ByteArrayOutputStream;
    import java.io.FileInputStream;
    import java.io.InputStream;
    import java.util.zip.Deflater;
    import java.util.zip.Inflater;
    
    public class Client {
    
      public static void main(String[] args) throws Exception {
        byte[] bytes = readFromFile("D:/testdeflate.txt");
        System.out.println("before compress: " + bytes.length);
        byte[] compressedBytes = compress(bytes);
        System.out.println("after compress: " + compressedBytes.length);
        byte[] decompressBytes = decompress(compressedBytes);
        System.out.println("after decompress: " + decompressBytes.length);
      }
    
      /**
       * 解压数据
       *
       * @param bytes 源数据
       * @return 压缩之后的数据
       */
      private static byte[] decompress(byte[] bytes) {
        Inflater inflater = new Inflater();
        //设置待解压数据
        inflater.setInput(bytes);
        byte[] buf = new byte[1024];
        try (ByteArrayOutputStream output = new ByteArrayOutputStream()) {
          //是否已解压完成
          while (!inflater.finished()) {
            //解压
            int len = inflater.inflate(buf);
            output.write(buf, 0, len);
          }
          //关闭资源
          inflater.end();
          return output.toByteArray();
        } catch (Exception e) {
          e.printStackTrace();
        }
        return new byte[0];
      }
    
      /**
       * 压缩数据
       *
       * @param bytes 源数据
       * @return 压缩之后的数据
       */
      private static byte[] compress(byte[] bytes) {
        Deflater deflater = new Deflater();
        //设置待压缩数据
        deflater.setInput(bytes);
        //表示压缩以当前输入内容结束,暂时不知道具体原理
        deflater.finish();
        byte[] buf = new byte[1024];
        try (ByteArrayOutputStream output = new ByteArrayOutputStream()) {
          //是否已压缩完成
          while (!deflater.finished()) {
            //压缩
            int len = deflater.deflate(buf);
            output.write(buf, 0, len);
          }
          //关闭资源
          deflater.end();
          return output.toByteArray();
        } catch (Exception e) {
          e.printStackTrace();
        }
        return new byte[0];
      }
    
      /**
       * 读取文件内容
       *
       * @param filePath 文件路径
       * @return 文件内容
       */
      private static byte[] readFromFile(String filePath) {
        int len = -1;
        byte[] buf = new byte[1024];
        try (InputStream input = new BufferedInputStream(new FileInputStream(filePath));
            ByteArrayOutputStream output = new ByteArrayOutputStream()) {
          while ((len = input.read(buf)) != -1) {
            output.write(buf, 0, len);
          }
          return output.toByteArray();
        } catch (Exception e) {
          e.printStackTrace();
        }
        return new byte[0];
      }
    }
    

    输出结果为

    before compress: 43435
    after compress: 1168
    after decompress: 43435
    

    可以看到数据从原来的43435字节压缩到了1168字节。

    使用DeflaterOutputStream和InflaterOutputStream解压缩

    import java.io.BufferedInputStream;
    import java.io.ByteArrayInputStream;
    import java.io.ByteArrayOutputStream;
    import java.io.FileInputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.util.zip.DeflaterOutputStream;
    import java.util.zip.InflaterInputStream;
    
    public class Client {
    
      public static void main(String[] args) throws IOException {
        byte[] bytes = readFromFile("D:/testdeflate.txt");
        System.out.println("before compress: " + bytes.length);
        byte[] compressedBytes = readFromFileAndCompress("D:/testdeflate.txt");
        System.out.println("after compress: " + compressedBytes.length);
        byte[] decompressBytes = readAndDecompress(compressedBytes);
        System.out.println("after decompress: " + decompressBytes.length);
      }
    
      /**
       * 读取文件内容并压缩
       *
       * @param filePath 文件路径
       * @return 文件内容
       */
      private static byte[] readFromFileAndCompress(String filePath) {
        int len = -1;
        byte[] buf = new byte[1024];
        try (InputStream input = new BufferedInputStream(new FileInputStream(filePath));
            ByteArrayOutputStream output = new ByteArrayOutputStream();
            DeflaterOutputStream dos = new DeflaterOutputStream(output)) {
          //从输入流读取写入到输出流
          while ((len = input.read(buf)) != -1) {
            dos.write(buf, 0, len);
          }
          //必须
          dos.finish();
          return output.toByteArray();
        } catch (Exception e) {
          e.printStackTrace();
        }
        return new byte[0];
      }
    
      /**
       * 读取文件内容
       *
       * @param filePath 文件路径
       * @return 文件内容
       */
      private static byte[] readFromFile(String filePath) {
        int len = -1;
        byte[] buf = new byte[1024];
        try (InputStream input = new BufferedInputStream(new FileInputStream(filePath));
            ByteArrayOutputStream output = new ByteArrayOutputStream()) {
          while ((len = input.read(buf)) != -1) {
            output.write(buf, 0, len);
          }
          return output.toByteArray();
        } catch (Exception e) {
          e.printStackTrace();
        }
        return new byte[0];
      }
    
      /**
       * 读取并解压缩
       *
       * @param bytes 待解压数据
       * @return 解压之后的数据
       */
      private static byte[] readAndDecompress(byte[] bytes) {
        int len = -1;
        byte[] buf = new byte[1024];
        try (InputStream input = new InflaterInputStream(new ByteArrayInputStream(bytes));
            ByteArrayOutputStream output = new ByteArrayOutputStream()) {
          while ((len = input.read(buf)) != -1) {
            output.write(buf, 0, len);
          }
          return output.toByteArray();
        } catch (IOException e) {
          e.printStackTrace();
        }
        return new byte[0];
      }
    }
    

    输出结果为

    before compress: 43435
    after compress: 1168
    after decompress: 43435
    

    可以看到和使用Deflater压缩的效果是一样的。DeflaterOutputStream写入完成之后必须调用finish()方法。

    /**
     * This class implements an output stream filter for compressing data in
     * the "deflate" compression format. It is also used as the basis for other
     * types of compression filters, such as GZIPOutputStream.
     *
     * @see         Deflater
     * @author      David Connelly
     * @since 1.1
     */
    public
    class DeflaterOutputStream extends FilterOutputStream {
        /**
         * 压缩类
         */
        protected Deflater def;
        /**
         * 重写了父类的write方法,先将数据压缩再写入
         */
        public void write(byte[] b, int off, int len) throws IOException {
            if (def.finished()) {
                throw new IOException("write beyond end of stream");
            }
            if ((off | len | (off + len) | (b.length - (off + len))) < 0) {
                throw new IndexOutOfBoundsException();
            } else if (len == 0) {
                return;
            }
            if (!def.finished()) {
                def.setInput(b, off, len);
                while (!def.needsInput()) {
                    deflate();
                }
            }
        }
    
       /**
         * 数据压缩
         */
        protected void deflate() throws IOException {
            int len = def.deflate(buf, 0, buf.length);
            if (len > 0) {
                out.write(buf, 0, len);
            }
        }
    }
    

    可以看到DeflaterOutputStream内部就是使用了Deflater来压缩数据,InflaterInputStream也是类似。

    使用GZipOutputStream和GZipInputStream解压缩

    import java.io.BufferedInputStream;
    import java.io.ByteArrayInputStream;
    import java.io.ByteArrayOutputStream;
    import java.io.FileInputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.util.zip.GZIPInputStream;
    import java.util.zip.GZIPOutputStream;
    
    public class Client {
    
      public static void main(String[] args) {
        byte[] bytes = readFromFile("D:/testdeflate.txt");
        System.out.println("before compress: " + bytes.length);
        byte[] compressedBytes = readFromFileAndCompress("D:/testdeflate.txt");
        System.out.println("after compress: " + compressedBytes.length);
        byte[] decompressBytes = readAndDecompress(compressedBytes);
        System.out.println("after decompress: " + decompressBytes.length);
      }
    
      /**
       * 读取文件内容
       *
       * @param filePath 文件路径
       * @return 文件内容
       */
      private static byte[] readFromFile(String filePath) {
        int len = -1;
        byte[] buf = new byte[1024];
        try (InputStream input = new BufferedInputStream(new FileInputStream(filePath));
            ByteArrayOutputStream output = new ByteArrayOutputStream()) {
          while ((len = input.read(buf)) != -1) {
            output.write(buf, 0, len);
          }
          return output.toByteArray();
        } catch (Exception e) {
          e.printStackTrace();
        }
        return new byte[0];
      }
    
      /**
       * 读取文件内容并压缩
       *
       * @param filePath 文件路径
       * @return 文件内容
       */
      private static byte[] readFromFileAndCompress(String filePath) {
        int len = -1;
        byte[] buf = new byte[1024];
        try (InputStream input = new BufferedInputStream(new FileInputStream(filePath));
            ByteArrayOutputStream output = new ByteArrayOutputStream();
            GZIPOutputStream dos = new GZIPOutputStream(output)) {
          while ((len = input.read(buf)) != -1) {
            dos.write(buf, 0, len);
          }
          //必须
          dos.finish();
          return output.toByteArray();
        } catch (Exception e) {
          e.printStackTrace();
        }
        return new byte[0];
      }
    
      /**
       * 读取并解压
       *
       * @param bytes 待解压数据
       * @return 解压之后的数据
       */
      private static byte[] readAndDecompress(byte[] bytes) {
        int len = -1;
        byte[] buf = new byte[1024];
        try (InputStream input = new GZIPInputStream(new ByteArrayInputStream(bytes));
            ByteArrayOutputStream output = new ByteArrayOutputStream()) {
          while ((len = input.read(buf)) != -1) {
            output.write(buf, 0, len);
          }
          return output.toByteArray();
        } catch (IOException e) {
          e.printStackTrace();
        }
        return new byte[0];
      }
    
    }
    

    输出结果为

    before compress: 43435
    after compress: 1180
    after decompress: 43435
    

    可以看到使用GZip相比Deflater,压缩之后的数据多了一些字节,这是因为GZipOutputStream就是DeflaterOutputStream的扩展类,在数据头部加入了10个字节的header数据,尾部加入了8个字节的CRC32的检验数据。

    可以看到Tomcat服务器对响应数据的压缩就使用到了GZipOutputStream。

  • 相关阅读:
    PHP学习——数组处理函数(一)
    PHP与MySQL的连接
    c语言:<tchar.h>
    PHP数组(二)
    PHP数组(一)
    PHP基础知识(三)
    Git和GitHub
    PHP基础知识(二)
    js 全选和反选(复选框)
    python 字典之删除
  • 原文地址:https://www.cnblogs.com/strongmore/p/14124841.html
Copyright © 2011-2022 走看看