当前位置: 首页 > news >正文

为什么.NET的System.IO.Compression无法解压zlib流,报错:System.IO.InvalidDataException

最近在做一些算法深入测试的工作,碰到了一些小问题,写出来给一些后来的同学们参考吧。

比如,有一段Stream,我们明知道他是zlib compress的流,用Java的 java.util.zip.InflaterInputStream可以轻松解压。

但是,当我们用.NET的System.IO.Compression类的DeflateStream写相关代码的时候,发现无法解压,报错:System.IO.InvalidDataException:“The archive entry was compressed using an unsupported compression method.” 这是为什么呢?

其实问题在于System.IO.Compression的DeflateStream,DeflateStream压缩和解压都采用的是Raw Deflate Stream, 而并非标准的ZLib Stream。

那Raw Deflate Stream和标准的ZLib Stream区别又在哪呢?

首先说一下Zlib压缩数据的格式规范(RFC 1950):

https://www.rfc-editor.org/rfc/rfc1950

2.2. Data formatA zlib stream has the following structure:0   1+---+---+|CMF|FLG|   (more-->)+---+---+(if FLG.FDICT set)0   1   2   3+---+---+---+---+|     DICTID    |   (more-->)+---+---+---+---++=====================+---+---+---+---+|...compressed data...|    ADLER32    |+=====================+---+---+---+---+Any data which may appear after ADLER32 are not part of the zlibstream.......

简而言之,ZLib压缩数据,需要标准的头和尾部数据。

其中头部2个字节,尾部4个字节。尤其是头数数据,表示压缩方法和模式:

先说头部2个字节:

0   1
+---+---+
|CMF|FLG|
+---+---+

1、第一个字节 CMF

其中前半个字节(高4位)表示 Compression method, 后半个字节(低4位)表示 Compression info。

2、第二个字节 FLG

第二个字节携带了3部分信息:

其实前5个字节(bits 0 ~ 4)表示  FCHECK—— check bits for CMF and FLG

第6个字节 ( bit 5) FDICK —— preset dictionary

第7,8 个字节 FLEVEL —— compression level

3、常见的几种头部信息:

78 01 - No Compression/low
78 9C - Default Compression
78 DA - Best Compression

而.NET的System.IO.Compression类的DeflateStream采集的Raw Deflate Stream并不包含这两部分信息,尤其是ZLib头部信息。

这时候再看我手上的代码,就几乎可以明白是什么原因无法解压了(以下信息为找印byte[]的hexdump信息):

compressed data hex: :
789c358e3d0b82501846fb0fcdfdb17e8df64aa91414514d41d11471c1ebc7626b9b4b7e5c1d52ca4baf0e0916a1ad5911677996f370005bdd0e601b455c87805f06b5528e3229c76a96811e11f93525fd62f174ae6ad12b8566cb30be0b0f04d74603a96b7b664013e34c5d23d67f1fbb6c59cf37c713a6e352b9095c84ed61058d49265c4da5c22987950021f12d474fc0272e09f6c9c7341997cc18194f7446633be49ec6a8a44594597e1e5ffe8df8064013858a

上面的数据前两个字节数据为0x78, 0x9c, 我们就可以看出他就是一串ZLib标准的压缩数据流,如果想用.NET的DeflateStream去解压这部分数据,也很简单——去掉ZLib的标准头部和尾部信息。

public static byte[] ZlibDecompress(byte[] data)
{using (MemoryStream decompressData = new MemoryStream()){data = data.Skip(2).ToArray();data = data.Take(data.Length - 4).ToArray();using (MemoryStream compressedStream = new MemoryStream(data)){using (DeflateStream deflateStream = new DeflateStream(compressedStream, CompressionMode.Decompress)){deflateStream.CopyTo(decompressData);utils.Bytes.PrintBytes("zlib decompress: ", decompressData.ToArray());}}return decompressData.ToArray();}
}

然后就解压成功了。

为什么没有讲尾部信息呢?因为尾部信息不重要,即使不去尾部信息,解压结果仍然一致:

至于压缩,因为DeflateStream的原因,压缩也是不会添加ZLib标准的头尾信息的,这点还是需要注意的。

下面是压缩代码:

public static void ZlibCompress(byte[] data)
{using (MemoryStream compressStream = new MemoryStream()) {using (MemoryStream memoryStream = new MemoryStream(data)){using (DeflateStream deflateStream = new DeflateStream(compressStream, CompressionMode.Compress)){memoryStream.CopyTo(deflateStream);}utils.Bytes.PrintBytes("deflateStream compress result: ", compressStream.ToArray());}}}

压缩结果,可以看出缺少了原数据的头部2个字节和尾部4个字节的数据。

http://www.dtcms.com/a/501534.html

相关文章:

  • 昆明住房和城乡建设局网站免费的网页空间
  • 天河网站建设服务快速搭建网站的软件
  • 嘉鱼网站建设多少钱wordpress置顶文章 调用
  • 建网站什么样的域名最好沈阳专业网站制作
  • 网站建设开发程序代码浙江省建设建材工会网站
  • 优化网站视频常熟有哪些网站建设公司
  • 问答网站如何优化如何进行个人网页制作
  • 网站建设岗位风险防控网站建设及运营
  • 住房和城乡建设部网站评估昆明网上房地产官网
  • 做视频可以领钱的网站都哪些网站可以做gif
  • 投资理财网站开发制作高端互联网网站
  • 外贸网站建设 评价海外音乐类网站做的比较好的
  • 网站服务器如何维护网络营销方案300字
  • 家居网站建设平台WordPress文章采集软件
  • 【机器学习入门】8.3 度量学习 —— 从距离度量到高维数据的 “合理比较”
  • 网站生成海报功能怎么做的创世网络网站建设
  • 福建住房和城乡建设局网站网站设计优缺点
  • C++——类和对象(3)
  • 无锡企业推广网站免费注册营业执照
  • 网站建设与运营公司的市场开发方案茂名市建设局网站
  • 茂名网站建设电话手机产品展示网站模板
  • 网站常用字体大小easy wordpress timelines
  • 网站界面网站设计技术公司
  • 莱芜网站制作个人响应式网站
  • 福永外贸网站建设公司大连百度推广排名优化
  • 做网站先学什么跨境电商是不是坑
  • 二级域名的网站备案青岛企业建站系统模板
  • 苏州园区一站式服务中心家装网站模板下载
  • 网络公司网站开发文创产品设计说明
  • 做网站包括图片设计吗湛江网站建设公司哪个好