亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

如何在c#中使用Zlib壓縮與解壓

 更新時(shí)間:2021年04月28日 08:51:28   作者:Compasslg  
這篇文章主要介紹了如何在c#中使用Zlib壓縮與解壓,幫助大家更好的理解和學(xué)習(xí)使用c#,感興趣的朋友可以了解下

介紹

近期用c#開(kāi)發(fā)一個(gè)游戲的存檔編輯工具需要用 Zlib 標(biāo)準(zhǔn)的 Deflate 算法對(duì)數(shù)據(jù)進(jìn)行解壓。 在 StackOverflow 上逛了一圈,發(fā)現(xiàn) c# 比較常用到的方式是微軟提供的 System.IO.Compression, zlib.net, 以及 ICSharpCode 的SharpZipLib。我簡(jiǎn)單的測(cè)試和包裝了一下,便在這里分享一下成果以及我個(gè)人的看法。

System.IO.Compression

通常來(lái)說(shuō),使用c#開(kāi)發(fā)時(shí)能用微軟官方提供的工具就盡量用,一個(gè)是bug會(huì)比較少,維護(hù)會(huì)比較穩(wěn)定。此外,官方提供的方案往往在優(yōu)化上也會(huì)高于第三方工具。

雖然在.NET Framework 4.5 開(kāi)始 System.IO.Compression.DeflateStream 也使用Zlib進(jìn)行Deflate格式的壓縮與解壓了,但經(jīng)過(guò)測(cè)試其壓縮和解壓結(jié)果與其他Zlib庫(kù)有所不同.
仔細(xì)觀察就會(huì)發(fā)現(xiàn),用 DeflateStream 壓縮后的數(shù)據(jù)開(kāi)頭比Zlib壓縮的數(shù)據(jù)少兩個(gè)字節(jié),結(jié)尾比Zlib少四個(gè)字節(jié); 這種輸出格式叫做 Raw Deflate 。
經(jīng)過(guò)查證,C# 提供的 DeflateStream只能壓縮成或者解壓這種Raw Deflate, 而不能處理標(biāo)準(zhǔn)的 Zlib Deflate 格式 (不過(guò)據(jù)說(shuō)可以自己生成); 但反過(guò)來(lái),Zlib 可以處理或生成這種不包含頭尾數(shù)據(jù)的Raw Deflate.
當(dāng)然,你也可以選擇手動(dòng)添加 header 和 trailer. 具體怎么添加可以閱讀文末鏈接的參考資料,由于不是特別重要,我就偷個(gè)懶了。

以下是我使用此方法簡(jiǎn)單包裝的壓縮與解壓數(shù)據(jù)的代碼:

// 使用System.IO.Compression進(jìn)行Deflate壓縮
public static byte[] MicrosoftCompress(byte[] data)
{
    MemoryStream uncompressed = new MemoryStream(data); // 這里舉例用的是內(nèi)存中的數(shù)據(jù);需要對(duì)文本進(jìn)行壓縮的話,使用 FileStream 即可
    MemoryStream compressed = new MemoryStream();
    DeflateStream deflateStream = new DeflateStream(compressed, CompressionMode.Compress); // 注意:這里第一個(gè)參數(shù)填寫(xiě)的是壓縮后的數(shù)據(jù)應(yīng)該被輸出到的地方
    uncompressed.CopyTo(deflateStream); // 用 CopyTo 將需要壓縮的數(shù)據(jù)一次性輸入;也可以使用Write進(jìn)行部分輸入
    deflateStream.Close();  // 在Close中,會(huì)先后執(zhí)行 Finish 和 Flush 操作。
    byte[] result = compressed.ToArray();
    return result;
}
// 使用System.IO.Compression進(jìn)行Deflate解壓
public static byte[] MicrosoftDecompress(byte[] data)
{
    MemoryStream compressed = new MemoryStream(data);
    MemoryStream decompressed = new MemoryStream();
    DeflateStream deflateStream = new DeflateStream(compressed, CompressionMode.Decompress); // 注意: 這里第一個(gè)參數(shù)同樣是填寫(xiě)壓縮的數(shù)據(jù),但是這次是作為輸入的數(shù)據(jù)
    deflateStream.CopyTo(decompressed); 
    byte[] result = decompressed.ToArray();
    return result;
}

zlib.net

zlib.net是一個(gè)非常小體量的開(kāi)源的第三方工具。經(jīng)過(guò)本人有限的研究和了解,這個(gè)庫(kù)其實(shí)更像是一個(gè)半成品,許多功能都不完善,不過(guò)優(yōu)點(diǎn)在于非常輕巧,而且與c++端使用 boost::iostreams::zlib 效果相同。

以下是用 zlib.net 提供的 ZOutputStream 類來(lái)壓縮數(shù)據(jù)的代碼

public static byte[] ZLibDotnetCompress(byte[] data)
{
    MemoryStream compressed = new MemoryStream();
    ZOutputStream outputStream = new ZOutputStream(compressed, 2); 
    outputStream.Write(data, 0, data.Length); // 這里采用的是用 Write 來(lái)寫(xiě)入需要壓縮的數(shù)據(jù);也可以采用和上面一樣的方法
    outputStream.Close();
    byte[] result = compressed.ToArray();
    return result;
}

以下是用zlib.net 提供的 ZInputStream 類來(lái)解壓數(shù)據(jù)的代碼

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, 只能提前準(zhǔn)備好輸出的 buffer 然后用 read 獲取定長(zhǎng)數(shù)據(jù)。
    inputStream.read(result, 0, result.Length); // 注意這里的 read 首字母是小寫(xiě)
    return result;
}

你需要通過(guò)read來(lái)獲取解壓后的數(shù)據(jù),同時(shí)你要在調(diào)用其解壓的方法時(shí)提前提供好外部的buffer用于儲(chǔ)存輸出的數(shù)據(jù),這個(gè)buffer的大小就是一個(gè)問(wèn)題了。
如果打算使用這個(gè)的話,建議除了儲(chǔ)存壓縮的數(shù)據(jù)以外,在不會(huì)被壓縮的位置添加壓縮前大小的數(shù)據(jù)。

但總體來(lái)說(shuō),個(gè)人不建議使用這個(gè)工具。

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

SharpZipLib

我最終選擇使用的是 SharpZipLib. (編輯:當(dāng)時(shí)沒(méi)做速度測(cè)試,且我需要解壓的文件不是太大,速度也不是很重要,否則的話不推薦選擇這個(gè)方案。。。)

ICSharpCode 不愧是開(kāi)發(fā)了 ILSpy 的團(tuán)隊(duì),SharpZipLib 在提供強(qiáng)大的功能的同時(shí),使用也很方便。限于主題,這里只討論用 Deflate 格式來(lái)壓縮數(shù)據(jù)流。

簡(jiǎn)單來(lái)說(shuō),你需要做的就是通過(guò) DeflaterOutputStream 來(lái)壓縮,InflaterInputStream 來(lái)解壓,而除了壓縮和解壓分在兩個(gè)不同的類以外,其他的操作方式和 System.IO.Compression.DeflateStream 可以做到完全一樣。
而且其壓縮和解壓的結(jié)果和直接使用Zlib官方的庫(kù)一模一樣,開(kāi)發(fā)輔助其他程序的工具時(shí)不用擔(dān)心頭尾數(shù)據(jù)的問(wèn)題,算是非常省事了。

以下是我使用該方案簡(jiǎn)單包裝的方法:

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();
}

速度對(duì)比

為了對(duì)比幾種方法在壓縮與解壓效率上的優(yōu)劣,我準(zhǔn)備了兩組數(shù)據(jù)做了一個(gè)簡(jiǎn)單的測(cè)試。

第一組為短數(shù)據(jù),是一個(gè)簡(jiǎn)單的字符串 "this is just a string for testing, see how this compression thing works."
第二組為長(zhǎng)數(shù)據(jù),是在網(wǎng)上下載到的英文版的 《冰與火之歌:權(quán)利的游戲》txt文本,大小約1.7mb。

我分別用每個(gè)方法壓縮和解壓短數(shù)據(jù)1000次,長(zhǎng)數(shù)據(jù)100次, 最終的結(jié)果如下:

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

顯而易見(jiàn)的,無(wú)論是長(zhǎng)數(shù)據(jù)還是短數(shù)據(jù)的壓縮與解壓,System.IO.Compression中提供的方法都優(yōu)于另外兩種方法。

Zlib.net在速度上的劣勢(shì)不明顯,而同樣的算法SharpZipLib要花兩到三倍的時(shí)間。

總結(jié)

最終,不出所料的,微軟官方提供的 System.IO.Compression 中的方法在速度上有著明顯的優(yōu)勢(shì);雖然不會(huì)提供Deflate的頭尾信息,但可以想辦法自己生成,而且這一缺點(diǎn)基本上是可以完全忽略的。 Zlib.net 雖然在速度上表現(xiàn)也不錯(cuò),同時(shí)也會(huì)生成Deflate壓縮的頭尾信息,但因?yàn)槠浒b比較潦草,使用起來(lái)相對(duì)不方便。而 SharpZipLib 很可惜,雖然其他各方面都很方便,但速度上的缺陷相當(dāng)致命,只能在一定需要 Deflate 而非 RawDeflate 或者使用的.Net Framework早于4.5的時(shí)候(且運(yùn)行中時(shí)間消耗不重要)偷懶的用一用了。

參考與延申

關(guān)于Zlib

https://zlib.net/

關(guān)于 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

關(guān)于CSharp System.IO.Compression.DeflateStream

https://docs.microsoft.com/en-us/dotnet/api/system.io.compression.deflatestream?view=net-5.0

開(kāi)發(fā)者之一 Mark Adler 在 StackOverflow 上的回答

deflate 和 compress 函數(shù)的區(qū)別

https://stackoverflow.com/questions/10166122/zlib-differences-between-the-deflate-and-compress-functions/10168441#10168441

如何手動(dòng)添加 header 和 trailer
https://stackoverflow.com/questions/39939869/data-format-for-system-io-compression-deflatestream

以上就是如何再c#中使用Zlib壓縮與解壓的詳細(xì)內(nèi)容,更多關(guān)于c#使用Zlib壓縮與解壓的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • C#使用Newtonsoft.Json中的JObject對(duì)象

    C#使用Newtonsoft.Json中的JObject對(duì)象

    本文詳細(xì)講解了C#使用Newtonsoft.Json中JObject對(duì)象的方法,文中通過(guò)示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-07-07
  • C# BackgroundWorker用法詳解

    C# BackgroundWorker用法詳解

    本篇文章主要介紹了C# BackgroundWorker使用詳解 ,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-04-04
  • C# datagridview、datagrid、GridControl增加行號(hào)代碼解析

    C# datagridview、datagrid、GridControl增加行號(hào)代碼解析

    今天這篇文章小編就來(lái)給大家分享關(guān)于C# datagridview、datagrid、GridControl增加行號(hào)的介紹,主要包括WinForm中datagridview增加行號(hào)、WPF中datagrid增加行號(hào)、WPF dev控件GridControl增加行號(hào)三個(gè)內(nèi)容,感興趣等我小伙伴可以參考一下
    2021-10-10
  • C#使用oledb操作excel文件的方法

    C#使用oledb操作excel文件的方法

    這篇文章主要介紹了C#使用oledb操作excel文件的方法,涉及C#中oledb操作excel的相關(guān)技巧,非常具有實(shí)用價(jià)值,需要的朋友可以參考下
    2015-05-05
  • C#中const 和 readonly 修飾符的用法詳解

    C#中const 和 readonly 修飾符的用法詳解

    這篇文章主要介紹了C#中const 和 readonly 修飾符的用法,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下
    2016-09-09
  • C#?將?Stream?保存到文件的方法

    C#?將?Stream?保存到文件的方法

    這篇文章主要介紹了C#將?Stream保存到文件的方法,文章圍繞主題展開(kāi)詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的朋友可以參考一下
    2022-08-08
  • C# 為String類型增加方法詳解

    C# 為String類型增加方法詳解

    下面小編就為大家?guī)?lái)一篇C# 為String類型增加方法詳解。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2016-07-07
  • C#利用雪花算法實(shí)現(xiàn)生成ID工具類

    C#利用雪花算法實(shí)現(xiàn)生成ID工具類

    雪花算法表示生成的ID如雪花般獨(dú)一無(wú)二,該算法源自Twitter,主要用于解決分布式系統(tǒng)的唯一Id生成問(wèn)題,本文主要介紹了C#如何利用利用雪花算法實(shí)現(xiàn)生成ID,需要的可以參考下
    2023-12-12
  • C#?使用原生?System.IO.Compression?實(shí)現(xiàn)?zip?的壓縮與解壓

    C#?使用原生?System.IO.Compression?實(shí)現(xiàn)?zip?的壓縮與解壓

    這篇文章主要介紹了C#?使用原生?System.IO.Compression?實(shí)現(xiàn)?zip?的壓縮與解壓,zip?是一個(gè)非常常見(jiàn)的壓縮包格式,本文主要用于說(shuō)明如何使用代碼?文件或文件夾壓縮為?zip壓縮包及其解壓操作,需要的朋友可以參考下
    2022-09-09
  • 淺析C#靜態(tài)類,靜態(tài)構(gòu)造函數(shù),靜態(tài)變量

    淺析C#靜態(tài)類,靜態(tài)構(gòu)造函數(shù),靜態(tài)變量

    這篇文章主要介紹了淺析C#靜態(tài)類,靜態(tài)構(gòu)造函數(shù),靜態(tài)變量 的相關(guān)資料,非常不錯(cuò)具有參考借鑒價(jià)值,需要的朋友可以參考下
    2016-06-06

最新評(píng)論