GZIP格式解析和Deflate静态Huffman解压缩

GZIP是封装了Deflate压缩的格式文件,Deflate使用了无压缩、Huffman+LZ77进行压缩,Huffman包括静态Huffman和动态Huffman。

Java实现了GZIP格式解析,静态Huffman解压缩,CRC32校验

gzip文件格式解析代码:

	    BinaryInputStream bis = new BinaryInputStream(bytes); // 二进制字节流读取类Header header = new Header();  // 读取GZIP headerheader.ID1 = bis.ReadUInt8();  // GZIP ID1header.ID2 = bis.ReadUInt8();  // GzIP ID2header.CM = bis.ReadUInt8();  header.Flag = bis.ReadUInt8();header.Time = bis.ReadUnix32TimeStamp(); header.Xfl = bis.ReadUInt8();header.OS = bis.ReadUInt8();gzip.header = header;Console.printlnf("ID=%xb%xb", header.ID1, header.ID2); // 打印Console.printlnf("CM=%xb", header.CM);Console.printlnf("Flag=%xb", header.Flag);Console.printlnf("MTime=%S", header.Time);Console.printlnf("XFL=%xb", header.Xfl);Console.printlnf("OS=%xb", header.OS);if ( (header.Flag & 0b00001000) != 0) {  // 如果标志位是文件名String filename = bis.ReadCString();Console.printlnf("filename=%S", filename);}else // 其他待实现throw new java.lang.IllegalArgumentException(header.Flag +"");byte[] result ; // 解压后的字节int data_len ;  // 解压前数据长度int crc;        // 程序计算解压后的CRC32(见上篇文章)if (header.CM == 8) { // deflate data_len = bytes.length - bis.GetPosition() - 8;			byte[] data = bis.ReadBytes(data_len);			result = Deflate.uncompress(data);  // 解压缩,返回解压后字节流crc = CRC.CRC32(result); // 计算循环冗余码}else // 待实现throw new java.lang.IllegalArgumentException(header.CM +""); gzip.crc = bis.ReadUInt32(); // gzip文件自身存储的crc32值gzip.isize = bis.ReadInt32(); System.out.println("gzip crc="+ Long.toHexString(gzip.crc) +",calc-crc=" + Integer.toHexString( crc) );

解析结果如下:

显示了GZIP标志、压缩方法、压缩时间、原始文件名、操作系统类型、CRC校验值

GZIP中存储的CRC32值==解压后计算的CRC32值。(0xa93145a2)

Deflate -静态Huffman解压缩:

	// 读取扩展Codeprivate static int ReadExtCode(BitsInputStream bis, int len) {bis.setOrder(BitOrder.LeftIsHigh);return bis.ReadBits(len);}// 读取距离private static int ReadDistance(BitsInputStream bis) {bis.setOrder(BitOrder.RightIsHigh);return bis.ReadBits(5);}// 读取Codeprivate static int ReadCode(BitsInputStream bis) {bis.setOrder(BitOrder.RightIsHigh);int code = bis.ReadBits(7);Integer value = FixHuffmanTable_7.get(code);if (value == null) {int ext = bis.ReadBit();code = (code << 1 | ext);value = FixHuffmanTable_8.get(code);if (value == null) {ext = bis.ReadBit();code = (code << 1 | ext);value = FixHuffmanTable_9.get(code);if (value == -1)throw new java.lang.IllegalArgumentException(code + "");}}return value;}// Deflate解压缩public static byte[] uncompress(final byte[] _input) throws IOException {IntArrayBuffer baos = new IntArrayBuffer();// 位流读取类BitsInputStream bis = new BitsInputStream(_input);int bFinal = bis.ReadBits(1); // 读取Deflate头,0 – 还有后续子块;1 – 该子块是最后一块。int bType = bis.ReadBits(2);  // 读取Deflate头,00 – 不压缩;01 – 静态Huffman编码压缩;10 – 动态Huffman编码压缩;11 – 保留while (true) {if (bType == 0) { // 无压缩int len = bis.ReadBits(16);int nlen = bis.ReadBits(16);assert len + nlen == 65535;throw new java.lang.IllegalArgumentException(bType + "");}else if (bType == 1) { // fixed Huffmanwhile (true) {int value = ReadCode(bis); // 读取Huffman codeif (value >= 0 && value <= 255) // literalbaos.Write(value);else if (value == 256) // 结束标志break ;else if (value >= 257 && value <= 285) {int length = LengthExtraCodeLengthsTable.get(value);int bits = LengthExtraCodeBitsTable.get(value); if (bits != 0) {int ext =  ReadExtCode(bis, bits); // 读取长度length = length + ext; }value = ReadDistance(bis); // 读取距离int distance = DistanceExtraCodeLengthsTable.get(value);bits = DistanceExtraCodeBitsTable.get(value);if (bits != 0) {int ext =ReadExtCode(bis , bits); // 读取距离distance = distance + ext; }// LZ77滑动窗口计算获取量int[] arr = baos.GetInts();int d = arr.length - distance;if (d < 0) {d = 0;length = length + distance - arr.length;}// 读取滑动窗口,写入到结果for (int i=0; i<length; i++) {	int m = arr[ d + i];baos.Write(m);arr = baos.GetInts();}}else throw new java.lang.IllegalArgumentException(value + "");}}else if (bType == 2) { // dynamic huffman 动态Huffman待实现throw new java.lang.IllegalArgumentException(bType + "");}else throw new java.lang.IllegalArgumentException(bType + "");if (bFinal == 1) // 最后一个块break ;}int[] b = baos.GetInts();byte[] result = new byte[b.length];for (int i=0; i<b.length; i++) result[i] = (byte) b[i];return result;

测试结果如下:

将字符串"abcabcabcabcabcabcabcabcabcabcabcabc1111"写入到文件

运行gzip程序压缩(系统程序)

使用Java程序对gzip文件解析并显示解压后的内容。 (gzip使用了静态huffman)。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/660797.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

浅谈 HTTPS

文章目录 HTTPS 简介HTTPS 特点与 HTTP 的区别HTTPS 工作流程1. 服务端生成密钥对2. 服务端申请数字证书3. 服务端发送数字证书4. 客户端验证数字证书5. 客户端解析证书内容6. 客户端传送加密信息7. 服务端解密信息8. 双方协商生成会话密钥并交换9. 使用会话密钥进行通信 总结 …

数据挖掘之基于K近邻算法的原油和纳斯达克股票数据预测分析

欢迎大家点赞、收藏、关注、评论啦 &#xff0c;由于篇幅有限&#xff0c;只展示了部分核心代码。 文章目录 一项目简介 二、功能三、系统四. 总结 一项目简介 一、项目背景 在当今日益复杂的金融市场中&#xff0c;准确地预测原油价格和纳斯达克股票市场的走势对于投资者、政…

【STM32】快速使用F407通用定时器输出可变PWM

网上的文章太啰嗦&#xff0c;这里直接开始。 使用的是STM32CubeIDE&#xff0c;HAL。以通用定时器TIM12在 通道2上输出1KHz的PWM为例。 要确定输出的引脚、定时器连接在哪里。 TIM2、3、4、5、12、13、14在APB1上&#xff0c;最大计数频率84M。 TIM1、8、9、10、11在APB2…

【docker 】Windows10安装 Docker

安装 Hyper-V Hyper-V 是微软开发的虚拟机&#xff0c;仅适用于 Windows 10。 按键&#xff1a; win键X &#xff0c;选着程序和功能 在查找设置中输入&#xff1a;启用或关闭Windows功能 选中Hyper-V 点击确定 安装 Docker Desktop for Windows Docker Desktop 官方下载…

vxeTable在vxe-modal提示工具栏无法关联表格

一般情况我们直接在created钩子中去关联工具栏&#xff0c;这样写正常情况下没有问题 const $tableRight this.$refs.tableRefRight;const $toolbarRight this.$refs.toolbarRefRight;if ($tableRight && $toolbarRight) {$tableRight.connect($toolbarRight);}在vxe…

管理能力学习笔记八:Will-Skill矩阵“盘“团队

如何把握带教中的“度”&#xff0c;才能在把事情做好的基础上&#xff0c;又能使员工获得成长呢&#xff1f; 需要做到 合理授权 & 适当辅导 如何做到&#xff1f; 通过使用 意愿-技能矩阵(Will-Skill Matrix) 辨别不同带教方法的适用情形&#xff0c;"盘"…

kube-prometheus部署到 k8s 集群

文章目录 **修改镜像地址****访问配置****修改 Prometheus 的 service****修改 Grafana 的 service****修改 Alertmanager 的 service****安装****Prometheus验证****Alertmanager验证****Grafana验证****卸载****Grafana显示时间问题** 或者配置ingress添加ingress访问grafana…

React复习笔记

基础语法 创建项目 借助脚手架&#xff0c;新建一个React项目(可以使用vite或者cra&#xff0c;这里使用cra) npx create-react-app 项目名 create-react-app是React脚手架的名称 启动项目 npm start 或者 yarn start src是源文件index.js相当于Vue的main.js文件。整个…

Go语言map

map 概念 在Go语言中&#xff0c;map 是一种内建的数据结构&#xff0c;它提供了一种关联式的存储机制&#xff0c;允许你以键值对的形式存储数据。每个键都是唯一的&#xff0c;并且与一个值相关联。你可以通过键来查找、添加、更新和删除值&#xff0c;这类似于其他编程语言…

低功耗数字IC后端设计实现典型案例| UPF Flow如何避免工具乱用Always On Buffer?

下图所示为咱们社区低功耗四核A7 Top Hierarchical Flow后端训练营中的一个案例&#xff0c;设计中存在若干个Power Domain&#xff0c;其中Power Domain2(简称PD2)为default Top Domain&#xff0c;Power Domain1&#xff08;简称PD1&#xff09;为一个需要power off的domain&…

Gateway Predicate断言(谓词)

是什么 Spring Cloud Gateway匹配路由作为Spring WebFlux HandlerMapping基础设施的一部分。 Spring Cloud Gateway包含许多内置的路由谓词工厂。 所有这些谓词都匹配HTTP请求的不同属性。 您可以使用逻辑 and 语句来联合收割机组合多个路由谓词工厂。 Predicate就是为了实现一…

开源、轻量、易用的服务器实时监控工具:哪吒探针

本文首发于只抄博客&#xff0c;欢迎点击原文链接了解更多内容。 前言 哪吒探针是一个开源、轻量、易用的服务器监控、运维工具&#xff0c;它有以下几个特点&#xff1a; 一键安装&#xff1a;可以一键安装面板与 Agent&#xff0c;并且支持 Linux、Windows、MacOS、OpenWRT…