在某些业务场景下,可能需要对字符串进行压缩与解压,压缩字符串可以使用 GZIPOutputStream 输出流来实现,而解压可以使用 GZIPInputStream 输入流来实现,下面先给出具体的参考代码,然后再分析其中的实现原理。

::: hljs-center

:::

1、代码实现

package com.magic.zip; 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; public class GzipUtils { /** * 压缩字符串 * * @param str 需要压缩的源字符串 * @return 压缩后的字符串 */ public static String compress(String str) { if (null == str || str.length() <= 0) { return str; } try (ByteArrayOutputStream out = new ByteArrayOutputStream(); GZIPOutputStream gzip = new GZIPOutputStream(out)) { // 将字符串以字节的形式写入到 GZIP 压缩输出流中 gzip.write(str.getBytes(StandardCharsets.UTF_8)); gzip.close(); return out.toString(StandardCharsets.ISO_8859_1.name()); } catch (IOException e) { e.printStackTrace(); } return str; } /** * 解压缩字符串 * * @param str 待解压的字符串 * @return 解压后的字符串 */ public static String decompress(String str) { if (str == null || str.length() == 0) { return str; } try (ByteArrayOutputStream out = new ByteArrayOutputStream(); ByteArrayInputStream in = new ByteArrayInputStream(str.getBytes(StandardCharsets.ISO_8859_1)); GZIPInputStream gunzip = new GZIPInputStream(in)) { byte[] buffer = new byte[256]; int n; // 从 GZIP 压缩输入流读取字节数据到 buffer 数组中 while ((n = gunzip.read(buffer)) >= 0) { out.write(buffer, 0, n); } return out.toString(StandardCharsets.UTF_8.name()); } catch (IOException e) { e.printStackTrace(); } return str; } }

2、原理分析

2.1 字符串压缩

字符串压缩的实现原理如下:

  • 首先构建 GZIPOutputStream 压缩输出流,然后将需要压缩的字符串写入输出流中,在写入 GZIPOutputStream 输出流的时候,就会使用 deflate 压缩算法对字符串进行压缩,具体的实现可以参考 GZIPOutputStream 的父类 DeflaterOutputStream 和默认的压缩器 Deflater 类的源码实现;

  • 将 GZIPOutputStream 压缩输出流转换为 ByteArrayOutputStream 字节数组输出流;

  • 最后再将 ByteArrayOutputStream 字节数组输出流转换为字符串 String ;

关于 GZIPOutputStream 和 ByteArrayOutputStream 类的源码分析,可以参考我写的另外两篇文章:

  • 串解压

压缩后的字符串解压缩的实现原理如下:

  • 首先使用压缩后的字符串构建字节数组输入流 ByteArrayInputStream ;

  • 然后使用 ByteArrayInputStream 字节数组输入流构建 GZIPInputStream 压缩输入流, GZIPInputStream 类主要就是用来读取 GZIP 格式的压缩数据的,这个过程会对压缩数据进行解压,具体压缩的实现可以参考 GZIPInputStream 的父类 InflaterInputStream 和默认的解压器 Inflater 类的源码实现;

  • 从 GZIPInputStream 压缩输入流中读取数据,然后再写入到 ByteArrayOutputStream 字节数组输出流中;

  • 最后再将 ByteArrayOutputStream 字节数组输出流转换为 String ,得到解压后的字符串;

关于 GZIPInputStream 、 ByteArrayInputStream 和 ByteArrayOutputStream 类的源码分析,可以参考我写的另外三篇文章:

  • 终将数据流转换为字符串时,都用到了 ByteArrayOutputStream 字节数组输出流。

2.3 字符编码

在压缩和解压的过程中,都需要先将字符串转换为字节流,然后再将字节流转换为字符串,转换的过程中会涉及到编码格式,比如在上面的示例代码中,使用到了两种编码格式: StandardCharsets.UTF_8 和 StandardCharsets.ISO_8859_1 ,压缩和解压的编码选择应该是一致的,否则可能会导致解压失败。

下面来简单分析一下 StandardCharsets 编码类。

lic final class StandardCharsets { /** 构造函数为私有的,不能被实例化 */ private StandardCharsets() { throw new AssertionError("No java.nio.charset.StandardCharsets instances for you!"); } /** US-ASCII(7位 ASCII 编码\ISO646-US\Basic Latin) */ public static final Charset US_ASCII = Charset.forName("US-ASCII"); /** ISO-8859-1(ISO 拉丁字母 编码\ISO-LATIN-1) */ public static final Charset ISO_8859_1 = Charset.forName("ISO-8859-1"); /** UTF-8(八位 UCS 转换格式) */ public static final Charset UTF_8 = Charset.forName("UTF-8"); /** UTF-16BE(十六位 UCS 转换格式, 大端字节序) */ public static final Charset UTF_16BE = Charset.forName("UTF-16BE"); /** UTF-16LE(十六位 UCS 转换格式, 小端字节序) */ public static final Charset UTF_16LE = Charset.forName("UTF-16LE"); /** UTF-16(十六位 UCS 转换格式,由可选字节顺序标记标识的字节顺序) */ public static final Charset UTF_16 = Charset.forName("UTF-16"); }

StandardCharsets 类位于 java.nio.charset 包下,它是一个标准字符集常量定义类,一共定义了6种字符集 Charset ,有常见的 UTF-8 和 ISO-8859-1 ,在平时的编码过程中,如果有使用到编码字符集,可以直接使用 StandardCharsets ,如果需要获取字符集的名称,可以调用 Charset 的 name() 方法或者 displayName() 方法,如下:

public static void main(String[] args) throws IOException { System.out.println(StandardCharsets.UTF_8.name()); System.out.println(StandardCharsets.UTF_8.displayName()); }

输出的结果都是 UTF-8 ,如下:

UTF-8 UTF-8

3、测试验证

下面来测试验证一下字符串的压缩与解压。

public static void main(String[] args) throws IOException { System.out.println(GzipUtils.compress("123456")); System.out.println(GzipUtils.decompress(compress("123456"))); }

运行程序,输出结果如下:

342615 aÓr 123456

从输出结果可以看出,字符串被压缩后,如果直接输出,得到的将会是乱码。

Java利用Gzip对字符串进行压缩与解压相关推荐

  1. 算法 - 赫夫曼编码(对字符串进行压缩 与 解压(解码)) - (对文件进行压缩解压)

    1.压缩:使用赫夫曼编码进行压缩 题目 构建赫夫曼树 package tree.huffmantree;import java.util.*;public class HuffmanCode {pub ...

  2. Java 使用 zip4j 进行基本的压缩、解压、设置密码操作(version zip4j-2.6.4)

    先看工具类 package space.util;import java.io.File; import java.util.List;import net.lingala.zip4j.ZipFile ...

  3. flutter 字符串zip压缩与解压

    1.添加zip依赖 dependencies:archive: ^2.0.13 archive 2.zip使用 import 'dart:io'; import 'dart:typed_data'; ...

  4. python3 zlib 实现压缩与解压字符串与文件数据流

    关于python3 zlib 压缩解压情况总结如下: 字符串:使用zlib.compress方法压缩字符串,使用zlib.decompress方法解压字符串. 数据流:压缩:zlib.compress ...

  5. 利用huffman编码对文本文件进行压缩与解压(java实现)

    利用huffman编码对文本文件进行压缩与解压 输入:一个文本文件 输出:压缩后的文件 算法过程: (1)统计文本文件中每个字符的使用频度 (2)构造huffman编码 (3)以二进制流形式压缩文件 ...

  6. Java实现文件压缩与解压[zip格式,gzip格式]

    原文:http://www.cnblogs.com/visec479/p/4112881.html#3069573 Java实现ZIP的解压与压缩功能基本都是使用了Java的多肽和递归技术,可以对单个 ...

  7. java利用正则截取字符串中的数字

    java利用正则截取字符串中的数字 String str = "xxx第47297章33";String regex = "\\d*";Pattern p = ...

  8. java gzip 解压文件_Java实现文件压缩与解压[zip格式,gzip格式]

    原文:http://www.cnblogs.com/visec479/p/4112881.html#3069573 Java实现ZIP的解压与压缩功能基本都是使用了Java的多肽和递归技术,可以对单个 ...

  9. java文件压缩与解压_Java实现文件压缩与解压

    Java实现ZIP的解压与压缩功能基本都是使用了Java的多肽和递归技术,可以对单个文件和任意级联文件夹进行压缩和解压,对于一些初学者来说是个很不错的实例.(转载自http://www.puiedu. ...

最新文章

  1. 不正确的c语言语句是,最基本的C语言语句是( )
  2. 2019夏第八周学习编辑总结
  3. Redis数据持久化机制AOF原理分析一---转
  4. 步进电机控制芯片_STK682/步进电机_STK682-010-E控制芯片 原创中文翻译
  5. JAVA 文件编译执行与虚拟机(JVM)简单介绍
  6. mysql57win10安装配置_Win10 OS安装(配置)MySQL 5.7(解压版)
  7. 网络游戏知识产权保护白皮书
  8. cs231n课程作业踩坑汇总
  9. Linux根据启动程序文件名称进行批量结束任务
  10. As-Conformal-As-Possible Surface Registration
  11. 大数据笔试面试问题之分治法解决
  12. linux的mongo主从异常,解决Linux系统下MongoDB数据库异常退出的问题
  13. 安卓抓包,为何总是 Tunnel to?
  14. 微信营销十一(微信公众号吸粉技巧)
  15. java爬虫新浪微博_java爬虫(爬新浪新闻) 如何从零开始
  16. 消费金融进入“第二赛段”,突围关键是什么?
  17. 【C语言快速上手】带你了解C语言,零基础入门①
  18. 春暖花开,我们去踏青
  19. 业务消息中心系统设计与实现(一)
  20. Excel比较两个工作表(Sheet)的两组列数据,并返回相应数据

热门文章

  1. 2D激光雷达和视觉相结合的SLAM概述
  2. 关于floor函数与ceil函数与round函数
  3. 程控电源CANoe上位机面板(CAN\ETH测试、RS232串口通信、编写设计思路)
  4. 如何修改PyCharm窗口背景颜色?
  5. 北大深院计算机录取难度保饰,她高考685分被北大录取却哭了,看到她的书桌,大家沉默了...
  6. 在CSS世界的权力——权重
  7. 管道、管程、管态的区别
  8. 5. Layui数据表格的快速使用
  9. 2022 年超详细过程步骤讲解 CentOS 7 安装Maven。以及Mavne配置文件的修改
  10. 阿里云CDN不止于加速:基于https国密算法构建安全数据传输链路