C#中對(duì)字符串進(jìn)行壓縮和解壓的實(shí)現(xiàn)
利用GZip和Brotli壓縮方法的優(yōu)勢(shì),減少字符串?dāng)?shù)據(jù)的大小,提高.NET核心應(yīng)用程序的性能。
在開(kāi)發(fā)應(yīng)用程序時(shí),你經(jīng)常需要處理字符串。由于字符串對(duì)象在性能方面的成本很高,你經(jīng)常想壓縮你的字符串內(nèi)容,即字符串對(duì)象中的數(shù)據(jù),以減少有效載荷。有幾個(gè)庫(kù)可以做到這一點(diǎn),但兩個(gè)流行的技術(shù)是GZip和Brotli。
在這篇文章中,我們將討論如何在C#中使用GZip和Brotli算法對(duì)字符串進(jìn)行壓縮和解壓。要使用這里提供的代碼示例,你的系統(tǒng)中應(yīng)該安裝有Visual Studio 2022。如果你還沒(méi)有副本,你可以在這里下載Visual Studio 2022。
在Visual Studio 2022中創(chuàng)建一個(gè)控制臺(tái)應(yīng)用程序項(xiàng)目
首先,讓我們?cè)赩isual Studio中創(chuàng)建一個(gè).NET Core控制臺(tái)應(yīng)用程序項(xiàng)目。假設(shè)你的系統(tǒng)中已經(jīng)安裝了Visual Studio 2022,按照下面的步驟創(chuàng)建一個(gè)新的.NET Core控制臺(tái)應(yīng)用程序項(xiàng)目:
- 啟動(dòng)Visual Studio IDE。
- 點(diǎn)擊 "創(chuàng)建一個(gè)新項(xiàng)目"。
- 在 "創(chuàng)建一個(gè)新項(xiàng)目 "窗口中,從顯示的模板列表中選擇 "控制臺(tái)應(yīng)用程序"。
- 點(diǎn)擊 "下一步"。
- 在接下來(lái)顯示的 "配置你的新項(xiàng)目 "窗口中,指定新項(xiàng)目的名稱和位置。
- 在 "其他信息 "窗口中,選擇.NET 6.0作為運(yùn)行時(shí)間,然后點(diǎn)擊下一步。
- 點(diǎn)擊 "創(chuàng)建"。
我們將使用這個(gè)項(xiàng)目來(lái)說(shuō)明下面的字符串壓縮和解壓縮。但首先我們要安裝一個(gè)基準(zhǔn)測(cè)試包BenchmarkDotNet,它將使我們能夠衡量我們從壓縮中獲得的好處。
安裝BenchmarkDotNet NuGet包
基準(zhǔn)測(cè)試代碼對(duì)于了解你的應(yīng)用程序的性能至關(guān)重要。在這篇文章中,我們將利用BenchmarkDotNet來(lái)跟蹤方法的性能。
要使用BenchmarkDotNet,你必須安裝BenchmarkDotNet軟件包。你可以通過(guò)Visual Studio 2022里面的NuGet軟件包管理器,或者在NuGet軟件包管理器控制臺(tái)執(zhí)行以下命令來(lái)完成。
Install-Package BenchmarkDotNet
C#中的System.IO.Compression命名空間
System.IO.Compression命名空間包括壓縮文件和字符串的方法。它包含兩種壓縮算法。GZip 和 Brotli。在接下來(lái)的章節(jié)中,我們將研究如何在C#中使用GZip和Brotli壓縮算法對(duì)字符串?dāng)?shù)據(jù)進(jìn)行壓縮和解壓。
我們將在下面的例子中使用以下文本。
string originalString = "To work with BenchmarkDotNet you must install the BenchmarkDotNet package. " + "You can do this either via the NuGet Package Manager inside the Visual Studio 2019 IDE, " + "or by executing the Install-Package BenchmarkDotNet command at the NuGet Package Manager Console";
在C#中使用GZip對(duì)數(shù)據(jù)進(jìn)行壓縮和解壓
下面的代碼片斷顯示了如何在C#中使用GZipStream類(lèi)來(lái)壓縮數(shù)據(jù)。注意,壓縮方法的參數(shù)是一個(gè)字節(jié)數(shù)組:
public static byte[] Compress(byte[] bytes) { using (var memoryStream = new MemoryStream()) { using (var gzipStream = new GZipStream(memoryStream, CompressionLevel.Optimal)) { gzipStream.Write(bytes, 0, bytes.Length); } return memoryStream.ToArray(); } }
要解壓使用GZip算法壓縮過(guò)的數(shù)據(jù),我們可以使用以下方法:
public static byte[] Decompress(byte[] bytes) { using (var memoryStream = new MemoryStream(bytes)) { using (var outputStream = new MemoryStream()) { using (var decompressStream = new GZipStream(memoryStream, CompressionMode.Decompress)) { decompressStream.CopyTo(outputStream); } return outputStream.ToArray(); } } }
運(yùn)行GZip壓縮算法
你可以使用下面的代碼片斷來(lái)執(zhí)行我們剛剛創(chuàng)建的GZip壓縮方法:
byte[] dataToCompress = Encoding.UTF8.GetBytes(originalString); byte[] compressedData = GZipCompressor.Compress(dataToCompress); string compressedString = Encoding.UTF8.GetString(compressedData); Console.WriteLine("Length of compressed string: " + compressedString.Length); byte[] decompressedData = GZipCompressor.Decompress(compressedData); string deCompressedString = Encoding.UTF8.GetString(decompressedData); Console.WriteLine("Length of decompressed string: " + deCompressedString.Length);
當(dāng)你運(yùn)行上述代碼時(shí),你會(huì)在控制臺(tái)窗口看到以下輸出:
圖1.GZip將原來(lái)259個(gè)字符的字符串壓縮成167個(gè)字符。
請(qǐng)注意,GZip從原始的259個(gè)字符的字符串中修剪了92個(gè)字符。因?yàn)樵甲址徒鈮汉蟮淖址畱?yīng)該是相同的,它們的長(zhǎng)度也應(yīng)該是相同的。
在C#中使用Brotli對(duì)數(shù)據(jù)進(jìn)行壓縮和解壓
下面的代碼片斷說(shuō)明了如何在C#中使用BrotliStream類(lèi)來(lái)壓縮數(shù)據(jù)。與上面的GZip例子一樣,注意壓縮方法的參數(shù)是一個(gè)字節(jié)數(shù)組:
public static byte[] Compress(byte[] bytes) { using (var memoryStream = new MemoryStream()) { using (var brotliStream = new BrotliStream(memoryStream, CompressionLevel.Optimal)) { brotliStream.Write(bytes, 0, bytes.Length); } return memoryStream.ToArray(); } }
而這里是你如何使用BrotliStream來(lái)解壓數(shù)據(jù)的:
public static byte[] Decompress(byte[] bytes) { using (var memoryStream = new MemoryStream(bytes)) { using (var outputStream = new MemoryStream()) { using (var decompressStream = new BrotliStream(memoryStream, CompressionMode.Decompress)) { decompressStream.CopyTo(outputStream); } return outputStream.ToArray(); } } }
運(yùn)行Brotli壓縮算法
下面的代碼片斷顯示了你如何使用我們上面創(chuàng)建的Brotli壓縮方法來(lái)壓縮一個(gè)字符串:
Console.WriteLine("Length of original string: " + originalString.Length); byte[] dataToCompress = Encoding.UTF8.GetBytes(originalString); byte[] compressedData = BrotliCompressor.Compress(dataToCompress); string compressedString = Convert.ToBase64String(compressedData); Console.WriteLine("Length of compressed string: " + compressedString.Length); byte[] decompressedData = BrotliCompressor.Decompress(compressedData); string deCompressedString = Convert.ToBase64String(decompressedData); Console.WriteLine("Length of decompressed string: " + deCompressedString.Length);
當(dāng)你運(yùn)行該程序時(shí),你將在控制臺(tái)窗口看到以下輸出:
圖2.Brotli將原來(lái)259個(gè)字符的字符串壓縮成121個(gè)字符。
正如你所看到的,Brotli的壓縮效果比GZip好得多。然而,壓縮率并不是故事的全部,我們將在下面看到。
用GZip和Brotli進(jìn)行異步壓縮和解壓
請(qǐng)注意,我們之前使用的壓縮和解壓方法也有異步的對(duì)應(yīng)方法。這里是使用GZip算法的壓縮和解壓方法的異步版本:
public async static Task<byte[]> CompressAsync(byte[] bytes) { using (var memoryStream = new MemoryStream()) { using (var gzipStream = new GZipStream(memoryStream, CompressionLevel.Optimal)) { await gzipStream.WriteAsync(bytes, 0, bytes.Length); } return memoryStream.ToArray(); } }
public async static Task<byte[]> DecompressAsync(byte[] bytes) { using (var memoryStream = new MemoryStream(bytes)) { using (var outputStream = new MemoryStream()) { using (var decompressStream = new GZipStream(memoryStream, CompressionMode.Decompress)) { await decompressStream.CopyToAsync(outputStream); } return outputStream.ToArray(); } } }
這里是使用Brotli的壓縮和解壓方法的異步版本:
public static async Task<byte[]> CompressAsync(byte[] bytes) { using (var memoryStream = new MemoryStream()) { using (var brotliStream = new BrotliStream(memoryStream, CompressionLevel.Optimal)) { await brotliStream.WriteAsync(bytes, 0, bytes.Length); } return memoryStream.ToArray(); } }
public static async Task<byte[]> DecompressAsync(byte[] bytes) { using (var memoryStream = new MemoryStream(bytes)) { using (var outputStream = new MemoryStream()) { using (var brotliStream = new BrotliStream(memoryStream, CompressionMode.Decompress)) { await brotliStream.CopyToAsync(outputStream); } return outputStream.ToArray(); } } }
在C#中用GZip和Brotli進(jìn)行壓縮和解壓的基準(zhǔn)測(cè)試
在我們之前創(chuàng)建的控制臺(tái)應(yīng)用程序項(xiàng)目中,創(chuàng)建一個(gè)名為BenchmarkCompression.cs的新文件并輸入以下代碼:
[MemoryDiagnoser] [Orderer(BenchmarkDotNet.Order.SummaryOrderPolicy.FastestToSlowest)] [RankColumn] public class BenchmarkCompression { string originalString = "To work with BenchmarkDotNet you must install the BenchmarkDotNet package. " + "You can do this either via the NuGet Package Manager inside the Visual Studio 2019 IDE, " + "or by executing the Install-Package BenchmarkDotNet command at the NuGet Package Manager Console"; [Benchmark] public void GZipCompress() { byte[] dataToCompress = Encoding.UTF8.GetBytes(originalString); var compressedData = GZipCompressor.Compress(dataToCompress); } [Benchmark] public void BrotliCompress() { byte[] dataToCompress = Encoding.UTF8.GetBytes(originalString); var compressedData = BrotliCompressor.Compress(dataToCompress); } }
當(dāng)你運(yùn)行基準(zhǔn)時(shí),你應(yīng)該看到類(lèi)似于下面圖3所示的控制臺(tái)輸出。
圖3.來(lái)自BenchmarkDotNet的結(jié)果...GZip贏了!
顯然,在選擇壓縮算法時(shí),壓縮率并不是唯一的考慮因素。盡管與GZip相比,你可以使用Brotli實(shí)現(xiàn)更好的壓縮,但額外的壓縮是以性能為代價(jià)的。GZip在壓縮和解壓數(shù)據(jù)方面明顯比Brotli快。
當(dāng)對(duì)你的.NET應(yīng)用程序進(jìn)行基準(zhǔn)測(cè)試時(shí),你應(yīng)該始終確保你的項(xiàng)目在發(fā)布模式下運(yùn)行。原因是編譯器為調(diào)試和發(fā)布模式優(yōu)化代碼的方式不同。關(guān)于基準(zhǔn)測(cè)試和應(yīng)用程序的性能,我在以后的文章中會(huì)有更多論述。
到此這篇關(guān)于C#中對(duì)字符串進(jìn)行壓縮和解壓的實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)C# 字符串壓縮和解壓內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C#驗(yàn)證碼識(shí)別類(lèi)完整實(shí)例
這篇文章主要介紹了C#驗(yàn)證碼識(shí)別類(lèi),以一個(gè)完整實(shí)例形式較為詳細(xì)的分析了驗(yàn)證碼圖片處理所涉及的各種常用技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-07-07ASP.NET總結(jié)C#中7種獲取當(dāng)前路徑的方法
本文主要介紹了7種獲取當(dāng)前路徑的方法,并做了代碼演示,分享給大家,感興趣的朋友可以參考一下。2016-03-03C# JSON格式化轉(zhuǎn)換輔助類(lèi) ConvertJson
本文介紹使用C#原生代碼實(shí)現(xiàn) JSON格式化以及各種類(lèi)型轉(zhuǎn)化JSON的輔助類(lèi),幫助開(kāi)發(fā)人員快速開(kāi)發(fā)。2016-04-04C#實(shí)現(xiàn)簡(jiǎn)易灰度圖和酷炫HeatMap熱力圖winform(附DEMO)
本文主要介紹了C#實(shí)現(xiàn)簡(jiǎn)易灰度圖和酷炫HeatMap熱力圖winform(附DEMO),文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-12-12C#實(shí)現(xiàn)簡(jiǎn)單播放mp3的方法
這篇文章主要介紹了C#實(shí)現(xiàn)簡(jiǎn)單播放mp3的方法,涉及C#播放多媒體文件的技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-03-03