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。

  • 相关阅读:
    1.27
    1.25
    Representation Learning with Contrastive Predictive Coding
    Learning a Similarity Metric Discriminatively, with Application to Face Verification
    噪声对比估计(负样本采样)
    Certified Adversarial Robustness via Randomized Smoothing
    Certified Robustness to Adversarial Examples with Differential Privacy
    Dynamic Routing Between Capsules
    Defending Adversarial Attacks by Correcting logits
    Visualizing Data using t-SNE
  • 原文地址:https://www.cnblogs.com/strongmore/p/14124841.html
Copyright © 2011-2022 走看看