GZIP压缩字符串

简介: GZIP压缩字符串

今天看了一个压缩字符串的方式,直接使用的Java8的API实现的。

Http中有三种压缩:

Zlib:常见类型有zip、rar和7z等。非常流行的文件压缩算法.在Linux 平台应用十分广泛

Deflate:更高的压缩率,7-zip就是实现的它,它还可以对gzip、PNG、MNG甚至Zip文件进行再次压缩从而得到比zlib压缩更小的大小.

Gzip:一种无损压缩算法,其基础为Deflate,两者差不多。

我们在Http请求头中可以看到支持的压缩算法,支持哪种就会显示哪种:

图片

Deflate是LZ77与哈弗曼编码的一个组合体。

基本原理是:对于要压缩的文件,首先使用LZ77算法的一个变种进行压缩,对得到的结果再使用哈夫曼编码(根据情况,使用静态哈弗曼编码或动态哈夫曼编码)的方法进行压缩。

那么什么是LZ77呢?

LZ77严格意义上来说不是一种算法,而是一种编码理论。它的核心思路是如果一个串中有两个重复的串,那么只需要知道后面的串与前面串重复的长度和后面串起始字符与前面串起始字符相对于起始位置的距离。

什么玩意,不好理解哈。

来举个例子:

比如字符串“不要啊不要啊停”,可以看到重复字符串有两个:“不要啊”

通过LZ77算法可压缩为“不要啊(4,3)停”,其中4表示重复的字符串起始字符(也就是第二个“不”)到第一个重复字符串起始字符(也就是第一个“不”)的距离,3表示重复字符串的长度。

由此可见,对要压缩的字符串是有要求的,重复度越高的字符串,压缩效果是越好!我通过生成UUID字符串测试了,1000个字符它给我压缩成了950个,啊哈哈,这压了个毛!

图片

那么哈夫曼编码是什么呢?

哈夫曼编码是数据结构课程中一种常见的算法。哈夫曼编码使用变长编码表对源符号进行编码,变长编码表通过一种评估来源符号出现概率的方法得到,出现概率较高的字母使用较短的编码,反之出现概率低的使用较长的编码,这样使编码之后的字符串的平均长度、期望值降低,从而达到无损压缩数据的目的。

好吧,这个我也不明白,数据结构中有讲,但是我没学。。。

下面是工具类代码:

package com.xing.parent.utils;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;

/**

  • 字符串压缩与解压缩
  • @author xinghua
    */
    public class CompressUtils {

    /**

    • 使用gzip压缩字符串
    • @param str 要压缩的字符串
    • @return str
      */
      public static String compress(String str) {
      if (str == null || str.length() == 0) {
      return str;
      }
      ByteArrayOutputStream out = new ByteArrayOutputStream();
      GZIPOutputStream gzip = null;
      try {

       gzip = new GZIPOutputStream(out);
       gzip.write(str.getBytes(StandardCharsets.UTF_8));
      

      }catch (Exception e) {

       e.printStackTrace();
      

      return str;
      }finally {
      if (gzip != null) {
      try {

               gzip.close();
           } catch (IOException e) {
               e.printStackTrace();
           }
       }
      

      }
      return new sun.misc.BASE64Encoder().encode(out.toByteArray());
      }

      /**

    • 使用gzip解压缩
    • @param compressedStr 要解压缩的字符串
    • @return 解压后的字符串
      */
      public static String unCompress(String compressedStr) {
      if (compressedStr == null || compressedStr.length() == 0) {
      return compressedStr;
      }
      ByteArrayOutputStream out = new ByteArrayOutputStream();
      ByteArrayInputStream inputStream = null;
      GZIPInputStream gzipInputStream = null;
      byte[] compressed;
      String decompressed;
      try {

       compressed = new sun.misc.BASE64Decoder().decodeBuffer(compressedStr);
       inputStream = new ByteArrayInputStream(compressed);
       gzipInputStream = new GZIPInputStream(inputStream);
       byte[] buffer = new byte[1024];
       int offset = -1;
      

      while ((offset = gzipInputStream.read(buffer)) != -1) {

           out.write(buffer, 0, offset);
       }
       decompressed = out.toString();
      

      } catch (IOException e) {

       e.printStackTrace();
      

      return compressedStr;
      } finally {
      if (gzipInputStream != null) {
      try {

               gzipInputStream.close();
           } catch (IOException e) {
               e.printStackTrace();
           }
       }
      

      if (inputStream != null) {
      try {

               inputStream.close();
           } catch (IOException e) {
               e.printStackTrace();
           }
       }
      

      try {

           out.close();
       } catch (IOException e) {
           e.printStackTrace();
       }
      

      }
      return decompressed;
      }

      public static void main(String[] args) {
      for(int i=0;i<10;i++){
      // String str1 = CommonUtil.getRandomStr(1000);

       String str1 = "我自己的报文,你自己整一个";
       System.out.println("压缩前大小:"+str1.length());
       long t1 = System.currentTimeMillis();
       String compress = CompressUtils.compress(str1);
       System.out.println("压缩后大小:"+compress.length()+"|耗时:"+(System.currentTimeMillis()-t1)+"ms->");
       long t2 = System.currentTimeMillis();
       String unCompress = CompressUtils.unCompress(compress);
       System.out.println("解压后大小:"+unCompress.length()+"|耗时:"+(System.currentTimeMillis()-t2)+"ms->");
       System.out.println("对比压缩前后字符串:"+unCompress.equals(str1));
      

      }
      }
      }

      我们的一个单个请求报文有17K,压缩后就可以剩下5K,耗时也在可接受范围,不错!

      今天学到了一个压缩算法,工作中还学到了netty通信的水位问题。

      按鼠标手指都磨起泡了。。。

      五一劳动节快乐!

END

目录
相关文章
|
存储 算法 Java
Android 进阶——代码插桩必知必会&ASM7字节码操作
Android 进阶——代码插桩必知必会&ASM7字节码操作
1764 0
|
存储 搜索推荐 算法
七大经典排序算法
七大经典排序算法
1800 0
|
8月前
|
存储 人工智能 自然语言处理
Gemini 2.5 Flash / Nano Banana 系统提示词泄露:全文解读+安全隐患分析
本文揭示了Nano Banana的内部系统指令,展示其如何通过“描绘不等于认可”原则,将图像生成请求无条件传递给下游模型,禁止自身进行内容审查。该机制凸显“先生成、后过滤”的安全架构,引发对生成边界与伦理的深层思考。
1124 6
Gemini 2.5 Flash / Nano Banana 系统提示词泄露:全文解读+安全隐患分析
|
UED
在钉钉宜搭中,要实现单选关联选项设置与图文展示的关联
【10月更文挑战第5天】本文通过具体案例介绍如何在钉钉宜搭中实现单选字段与其他字段的联动功能。以旅行社旅游线路报名表单为例,详细说明了创建单选字段、图文展示字段及设置联动逻辑的具体步骤。通过简单的配置,实现了用户选择目的地后自动展示相关信息的效果,提升了用户体验和数据录入准确性。适用于希望通过低代码平台优化工作流程的企业。
1219 6
|
存储 JavaScript 前端开发
看过来!准确直观显示手机充电信息的充电统计软件!
基于自制充电统计App,多设备用户可远程查看各设备充电数据。在软件内可以查看预估充电容量等信息
|
Ubuntu
掌握Ubuntu 22.04的关机和重启命令:轻松操作系统的新方式
Ubuntu 22.04作为一款备受期待的操作系统版本,带来了许多令人惊喜的新功能。在这篇文章中,我们将向您介绍如何使用命令行来进行关机和重启操作,让您轻松掌握Ubuntu 22.04的新特性。
5878 0
掌握Ubuntu 22.04的关机和重启命令:轻松操作系统的新方式
|
Linux 网络安全
通过 vscode Remote-SSH 远程开发Linux上的代码
通过 vscode Remote-SSH 远程开发Linux上的代码
743 0
|
缓存 监控 前端开发
前端性能优化:从系统分析到实践策略
**前端性能优化概述** 本文探讨了前端性能优化的重要性,强调了从整体角度而非仅关注局部优化手段的必要性。作者指出,建立性能评价系统是关键,通过**性能指标**(如FP、FCP、LCP、CLS等)来量化页面性能,然后使用**性能监控**工具收集数据。文章列举了9个关键性能指标,并介绍了如何通过SDK或工具进行数据收集。 在实际操作中,文章提到了**性能优化方法论**,包括了解何时何地出现性能问题,以及如何根据性能指标采取相应优化措施。作者推荐使用Chrome的Lighthouse工具进行性能测试,并讨论了**CDN**、**缓存策略**和**懒加载**作为常见的优化手段。
513 0
|
人工智能 自然语言处理 小程序
用户说 | 文科生的我用DeepSeek+AI程序员半小时开发了一个小程序
用户说 | 文科生的我用DeepSeek+AI程序员半小时开发了一个小程序
用户说 | 文科生的我用DeepSeek+AI程序员半小时开发了一个小程序
|
Ubuntu Linux
Ubuntu 20.04 右键扩展在vscode中打开
Ubuntu 20.04 右键扩展在vscode中打开
1763 0
Ubuntu 20.04 右键扩展在vscode中打开

热门文章

最新文章