標籤:
C#編程總結(十三)資料壓縮
在進行檔案儲存體或者資料轉送時,為了節省空間的流量,需要對資料或檔案進行壓縮。在這裡我們講述通過C#實現資料壓縮。
一、GZipStream壓縮
微軟提供用於壓縮和解壓縮流的方法。
此類表示 GZip 資料格式,它使用無損壓縮和解壓縮檔案的行業標準演算法。 這種格式包括一個檢測資料損毀的迴圈冗餘校正值。 GZip 資料格式使用的演算法與 DeflateStream 類的演算法相同,但它可以擴充以使用其他壓縮格式。 這種格式可以通過不涉及專利使用權的方式輕鬆實現。
可以使用許多常見的壓縮公用程式對寫入到副檔名為 .gz 的檔案的壓縮 GZipStream 對象進行解壓縮;但是,此類原本並不提供用於向 .zip 存檔中添加檔案或從 .zip 存檔中提取檔案的功能。
DeflateStream 和 GZipStream 中的壓縮功能作為流公開。 由於資料是以逐位元組的方式讀取的,因此無法通過進行多次傳遞來確定壓縮整個檔案或大型資料區塊的最佳方法。 對於未壓縮的資料來源,最好使用 DeflateStream 和 GZipStream 類。 如果來源資料已壓縮,則使用這些類時實際上可能會增加流的大小。
具體實現源碼
1、壓縮位元組數組
/// <summary> /// 壓縮位元組數組 /// </summary> /// <param name="str"></param> public static byte[] Compress(byte[] inputBytes) { using (MemoryStream outStream = new MemoryStream()) { using (GZipStream zipStream = new GZipStream(outStream, CompressionMode.Compress, true)) { zipStream.Write(inputBytes, 0, inputBytes.Length); zipStream.Close(); //很重要,必須關閉,否則無法正確解壓 return outStream.ToArray(); } } } /// <summary> /// 解壓縮位元組數組 /// </summary> /// <param name="str"></param> public static byte[] Decompress(byte[] inputBytes) { using (MemoryStream inputStream = new MemoryStream(inputBytes)) { using (MemoryStream outStream = new MemoryStream()) { using (GZipStream zipStream = new GZipStream(inputStream, CompressionMode.Decompress)) { zipStream.CopyTo(outStream); zipStream.Close(); return outStream.ToArray(); } } } }2、壓縮字串
在壓縮位元組的基礎擴充而來,注意字元轉換,保證不出現亂碼。具體原理,這裡不再介紹,可見:
C#編程總結(十)字元轉碼 http://www.cnblogs.com/yank/p/3536863.html
/// <summary> /// 壓縮字串 /// </summary> /// <param name="input"></param> /// <returns></returns> public static string Compress(string input) { byte[] inputBytes = Encoding.Default.GetBytes(input); byte[] result = Compress(inputBytes); return Convert.ToBase64String(result); } /// <summary> /// 解壓縮字串 /// </summary> /// <param name="input"></param> /// <returns></returns> public static string Decompress(string input) { byte[] inputBytes = Convert.FromBase64String(input); byte[] depressBytes = Decompress(inputBytes); return Encoding.Default.GetString(depressBytes); }3、壓縮檔
如果你試圖自己做一個壓縮公用程式,相比這個方法很管用
/// <summary> /// 壓縮目錄 /// </summary> /// <param name="dir"></param> public static void Compress(DirectoryInfo dir) { foreach (FileInfo fileToCompress in dir.GetFiles()) { Compress(fileToCompress); } } /// <summary> /// 解壓縮目錄 /// </summary> /// <param name="dir"></param> public static void Decompress(DirectoryInfo dir) { foreach (FileInfo fileToCompress in dir.GetFiles()) { Decompress(fileToCompress); } } /// <summary> /// 壓縮檔 /// </summary> /// <param name="fileToCompress"></param> public static void Compress(FileInfo fileToCompress) { using (FileStream originalFileStream = fileToCompress.OpenRead()) { if ((File.GetAttributes(fileToCompress.FullName) & FileAttributes.Hidden) != FileAttributes.Hidden & fileToCompress.Extension != ".gz") { using (FileStream compressedFileStream = File.Create(fileToCompress.FullName + ".gz")) { using (GZipStream compressionStream = new GZipStream(compressedFileStream, CompressionMode.Compress)) { originalFileStream.CopyTo(compressionStream); } } } } } /// <summary> /// 解壓縮檔案 /// </summary> /// <param name="fileToDecompress"></param> public static void Decompress(FileInfo fileToDecompress) { using (FileStream originalFileStream = fileToDecompress.OpenRead()) { string currentFileName = fileToDecompress.FullName; string newFileName = currentFileName.Remove(currentFileName.Length - fileToDecompress.Extension.Length); using (FileStream decompressedFileStream = File.Create(newFileName)) { using (GZipStream decompressionStream = new GZipStream(originalFileStream, CompressionMode.Decompress)) { decompressionStream.CopyTo(decompressedFileStream); } } } }
二、開源組件ICSharpCode.SharpZipLib進行壓縮
ICSharpCode.SharpZipLib,開源組件,支援Zip,GZip,BZip2,Tar等
其壓縮效率及壓縮比比微軟內建的要好。並提供了源碼,開源對其演算法進行研究、改進。具體可見:
http://www.icsharpcode.net/OpenSource/SharpZipLib/
這裡提供簡單的一種實現以供參考,其他演算法比較類似,不再贅述。
1、使用BZip2壓縮字串
/// <summary> /// 壓縮 /// </summary> /// <param name="input"></param> /// <returns></returns> public static string Compress(string input) { string result = string.Empty; byte[] buffer = Encoding.UTF8.GetBytes(input); using (MemoryStream outputStream = new MemoryStream()) { using (BZip2OutputStream zipStream = new BZip2OutputStream(outputStream)) { zipStream.Write(buffer, 0, buffer.Length); zipStream.Close(); } return Convert.ToBase64String(outputStream.ToArray()); } } /// <summary> /// 解壓縮 /// </summary> /// <param name="input"></param> /// <returns></returns> public static string Decompress(string input) { string result = string.Empty; byte[] buffer = Convert.FromBase64String(input); using (Stream inputStream = new MemoryStream(buffer)) { BZip2InputStream zipStream = new BZip2InputStream(inputStream); using (StreamReader reader = new StreamReader(zipStream, Encoding.UTF8)) { //輸出 result = reader.ReadToEnd(); } } return result; }三、Demo
http://files.cnblogs.com/yank/CompressSample.zip
四、後續
如有其他更好的壓縮方法,請指出。後續會更新至此。
C#編程總結(十三)資料壓縮