目录

介绍

System.IO.Compression

zlib.net

SharpZipLib

速度对比

总结

参考与延申

关于Zlib

关于 Deflate 和 Raw Deflate

关于CSharp System.IO.Compression.DeflateStream

开发者之一 Mark Adler 在 StackOverflow 上的回答


介绍

近期用c#开发一个游戏的存档编辑工具需要用 Zlib 标准的 Deflate 算法对数据进行解压。 在 StackOverflow 上逛了一圈,发现 c# 比较常用到的方式是微软提供的 System.IO.Compression, zlib.net, 以及 ICSharpCode 的SharpZipLib。我简单的测试和包装了一下,便在这里分享一下成果以及我个人的看法。

System.IO.Compression

通常来说,使用c#开发时能用微软官方提供的工具就尽量用,一个是bug会比较少,维护会比较稳定。此外,官方提供的方案往往在优化上也会高于第三方工具。

虽然在.NET Framework 4.5 开始 System.IO.Compression.DeflateStream 也使用Zlib进行Deflate格式的压缩与解压了,但经过测试其压缩和解压结果与其他Zlib库有所不同.
仔细观察就会发现,用 DeflateStream 压缩后的数据开头比Zlib压缩的数据少两个字节,结尾比Zlib少四个字节; 这种输出格式叫做 Raw Deflate 。
经过查证,C# 提供的 DeflateStream只能压缩成或者解压这种Raw Deflate, 而不能处理标准的 Zlib Deflate 格式 (不过据说可以自己生成); 但反过来,Zlib 可以处理或生成这种不包含头尾数据的Raw Deflate.
当然,你也可以选择手动添加 header 和 trailer. 具体怎么添加可以阅读文末链接的参考资料,由于不是特别重要,我就偷个懒了。

// 使用System.IO.Compression进行Deflate压缩
public static byte[] MicrosoftCompress(byte[] data)
{MemoryStream uncompressed = new MemoryStream(data); // 这里举例用的是内存中的数据;需要对文本进行压缩的话,使用 FileStream 即可MemoryStream compressed = new MemoryStream();DeflateStream deflateStream = new DeflateStream(compressed, CompressionMode.Compress); // 注意:这里第一个参数填写的是压缩后的数据应该被输出到的地方uncompressed.CopyTo(deflateStream); // 用 CopyTo 将需要压缩的数据一次性输入;也可以使用Write进行部分输入deflateStream.Close();  // 在Close中,会先后执行 Finish 和 Flush 操作。byte[] result = compressed.ToArray();return result;
}
// 使用System.IO.Compression进行Deflate解压
public static byte[] MicrosoftDecompress(byte[] data)
{MemoryStream compressed = new MemoryStream(data);MemoryStream decompressed = new MemoryStream();DeflateStream deflateStream = new DeflateStream(compressed, CompressionMode.Decompress); // 注意: 这里第一个参数同样是填写压缩的数据,但是这次是作为输入的数据deflateStream.CopyTo(decompressed); byte[] result = decompressed.ToArray();return result;
}

zlib.net

zlib.net是一个非常小体量的开源的第三方工具。经过本人有限的研究和了解,这个库其实更像是一个半成品,许多功能都不完善,不过优点在于非常轻巧,而且与c++端使用 boost::iostreams::zlib 效果相同。

以下是用 zlib.net 提供的 ZOutputStream 类来压缩数据的代码

public static byte[] ZLibDotnetCompress(byte[] data)
{MemoryStream compressed = new MemoryStream();ZOutputStream outputStream = new ZOutputStream(compressed, 2); outputStream.Write(data, 0, data.Length); // 这里采用的是用 Write 来写入需要压缩的数据;也可以采用和上面一样的方法outputStream.Close();byte[] result = compressed.ToArray();return result;
}

以下是用zlib.net 提供的 ZInputStream 类来解压数据的代码

public static byte[] ZLibDotnetDecompress(byte[] data, int size)
{MemoryStream compressed = new MemoryStream(data);ZInputStream inputStream = new ZInputStream(compressed);byte[] result = new byte[size];   // 由于ZInputStream 继承的是BinaryReader而不是Stream, 只能提前准备好输出的 buffer 然后用 read 获取定长数据。inputStream.read(result, 0, result.Length); // 注意这里的 read 首字母是小写return result;
}

你需要通过read来获取解压后的数据,同时你要在调用其解压的方法时提前提供好外部的buffer用于储存输出的数据,这个buffer的大小就是一个问题了。
如果打算使用这个的话,建议除了储存压缩的数据以外,在不会被压缩的位置添加压缩前大小的数据。

但总体来说,个人不建议使用这个工具。

https://github.com/zyborg/zlib.net
http://www.componentace.com/zlib_.NET.htm

SharpZipLib

我最终选择使用的是 SharpZipLib. (编辑:当时没做速度测试,且我需要解压的文件不是太大,速度也不是很重要,否则的话不推荐选择这个方案。。。)

ICSharpCode 不愧是开发了 ILSpy 的团队,SharpZipLib 在提供强大的功能的同时,使用也很方便。限于主题,这里只讨论用 Deflate 格式来压缩数据流。

简单来说,你需要做的就是通过 DeflaterOutputStream 来压缩,InflaterInputStream 来解压,而除了压缩和解压分在两个不同的类以外,其他的操作方式和 System.IO.Compression.DeflateStream 可以做到完全一样。
而且其压缩和解压的结果和直接使用Zlib官方的库一模一样,开发辅助其他程序的工具时不用担心头尾数据的问题,算是非常省事了。

以下是我使用该方案简单包装的方法:

public static byte[] SharpZipLibCompress(byte[] data)
{MemoryStream compressed = new MemoryStream();DeflaterOutputStream outputStream = new DeflaterOutputStream(compressed);outputStream.Write(data, 0, data.Length);outputStream.Close();return compressed.ToArray();
}
public static byte[] SharpZipLibDecompress(byte[] data)
{MemoryStream compressed = new MemoryStream(data);MemoryStream decompressed = new MemoryStream();InflaterInputStream inputStream = new InflaterInputStream(compressed);inputStream.CopyTo(decompressed);return decompressed.ToArray();
}

速度对比

为了对比几种方法在压缩与解压效率上的优劣,我准备了两组数据做了一个简单的测试。

第一组为短数据,是一个简单的字符串 “this is just a string for testing, see how this compression thing works.”
第二组为长数据,是在网上下载到的英文版的 《冰与火之歌:权利的游戏》txt文本,大小约1.7mb。

我分别用每个方法压缩和解压短数据1000次,长数据100次, 最终的结果如下:

Length of Short Data: 144
Length of Long Data: 1685502============================================
Compress and decompress with Microsoft Zlib Compression (1000 times): 54
Compress and decompress with Microsoft Zlib Compression (long data 100 times): 7924============================================
Compress and decompress with Zlib.net Compression (1000 times): 254
Compress and decompress with Zlib.net Compression (long data 100 times): 9924============================================
Compress and decompress with SharpZipLib Compression (1000 times): 442
Compress and decompress with SharpZipLib Compression (long data 100 times): 26782

显而易见的,无论是长数据还是短数据的压缩与解压,System.IO.Compression中提供的方法都优于另外两种方法。

Zlib.net在速度上的劣势不明显,而同样的算法SharpZipLib要花两到三倍的时间。

总结

最终,不出所料的,微软官方提供的 System.IO.Compression 中的方法在速度上有着明显的优势;虽然不会提供Deflate的头尾信息,但可以想办法自己生成,而且这一缺点基本上是可以完全忽略的。 Zlib.net 虽然在速度上表现也不错,同时也会生成Deflate压缩的头尾信息,但因为其包装比较潦草,使用起来相对不方便。而 SharpZipLib 很可惜,虽然其他各方面都很方便,但速度上的缺陷相当致命,只能在一定需要 Deflate 而非 RawDeflate 或者使用的.Net Framework早于4.5的时候(且运行中时间消耗不重要)偷懒的用一用了。

参考与延申

关于Zlib

zlib Home Site

关于 Deflate 和 Raw Deflate

https://stackoverflow.com/questions/37845440/net-deflatestream-vs-linux-zlib-difference
https://www.ietf.org/rfc/rfc1950.txt
https://www.ietf.org/rfc/rfc1951.txt

关于CSharp System.IO.Compression.DeflateStream

DeflateStream Class (System.IO.Compression) | Microsoft Docs

开发者之一 Mark Adler 在 StackOverflow 上的回答

deflate 和 compress 函数的区别
https://stackoverflow.com/questions/10166122/zlib-differences-between-the-deflate-and-compress-functions/10168441#10168441

如何手动添加 header 和 trailer
https://stackoverflow.com/questions/39939869/data-format-for-system-io-compression-deflatestream

c#中使用Zlib压缩与解压的方法相关推荐

  1. linux中常用的压缩、解压命令详解

    不管在windows中还是在linux中,我们会经常看到各种压缩的文件,此刻我们需要使用就得解压,在这就介绍介绍linux中解压.压缩的命令. 在做实验之前,我们先创建几个文件,大小都是100M,方便 ...

  2. android下载zip到assets,Android将assets中的zip压缩文件解压到SD卡

    程序首先要获取写外部存储权限: 程序: package com.hu.andstar; import java.io.File; import java.io.FileOutputStream; im ...

  3. Linux 中的文件压缩与解压

    .tar tar xvf FileName.tar # 解压 tar cvf FileName.tar DirName # 压缩 .gz gunzip FileName.gz # 解压 gzip -d ...

  4. java解压zip包_Java中文件的压缩与解压,每天进步一点点系列

    使用java.util.zip包,实现文件的压缩与解压,并提供了下载方法 注意 无论是调用createNewFile()创建文件,还是在创建输出流时由输出流负责创建文件,都必须保证父路径已经存在,否则 ...

  5. 收集总结java中压缩、解压文件方法

    1.使用GZIPOutputStream压缩文件: @org.junit.Testpublic void test013 (){String str = "F:\\MyTest\\myTes ...

  6. tarfile读文件python_Python中使用tarfile压缩、解压tar归档文件示例

    Python自带的tarfile模块可以方便读取tar归档文件,牛b的是可以处理使用gzip和bz2压缩归档文件tar.gz和tar.bz2. 与tarfile对应的是zipfile模块,zipfil ...

  7. Python中使用tarfile压缩、解压tar归档文件

    Python自带的tarfile模块可以方便读取tar归档文件,牛b的是可以处理使用gzip和bz2压缩归档文件tar.gz和tar.bz2. 与tarfile对应的是zipfile模块,zipfil ...

  8. VC++使用zlib压缩及解压数据,使用base64编码及解码数据(附源码)

    VC++常用功能开发汇总(专栏文章列表,欢迎订阅,持续更新...)https://blog.csdn.net/chenlycly/article/details/124272585C++软件异常排查从 ...

  9. python 压缩与解压文件

    文件copy模块shutil 高级的文件.文件夹.压缩包处理模块 shutil.copyfileobj() 将文件内容拷贝到另一个文件中 shutil.copyfile() 拷贝文件 import s ...

最新文章

  1. C语言strstr()函数(在主字符串里查找子字符串,返回第一次找到的子字符串以及后面的字符串)
  2. Linux学习笔记(3)linux服务管理与启停
  3. 游戏行业的人工智能设计(二):路径搜寻和感知
  4. LINQ-to-SQL那点事~关于延时加载的性能,微软给出了不错的解决方案
  5. Unity C# Job System介绍(一) Job System总览和多线程
  6. 操作系统——进程的状态及转换
  7. 查看监控Heap size 和 JVM 垃圾回收情况
  8. 新浪纯微博html5版,官方出品的精简版!新浪微博轻版App体验
  9. Jetson开发实战记录(二):Jetson Xavier NX版本区别以及烧录系统
  10. 6款实用网页开发和设计工具
  11. 黑苹果安装教程---联想G480安装懒人版10.9.5
  12. 安卓升级AndroidX手把手教程
  13. JavaScript实现下雪效果
  14. mysql数据库误删恢复
  15. 成功焊接BGA芯片技巧
  16. 山茶油的功效与食用方法
  17. golang使用josn.Unmarshal报错:unexpected end of JSON input
  18. 如何关闭win10防火墙_如何彻底关闭win10自带杀毒软件:windows defender?
  19. 关于html video 在chrome浏览器下无法快进问题解决
  20. 【String类和标准模板库】

热门文章

  1. office2003和2007共存不冲突的解决方案
  2. 星网宇达(惯导+IMU)设备实现自动采点
  3. 文华财经期货量化高抛低吸程序化指标公式,无未来函数红涨绿跌多空均线系统信号
  4. Android2018年必须知道的史上最全框架、最全开源App
  5. 如何为深澜设置自动登录(PPPOE)
  6. excel中文名转为英文名,姓和名的第一个字母大写,中间留空格
  7. 软件批量安装,软件自动安装,一键安装合集
  8. linux多个文件打包命令行,Linux下文档的压缩和打包命令
  9. 数字孪生技术在建筑行业的应用详情分析
  10. windows快捷键隐藏桌面所有窗口——“老板键”