在進行文件存儲或者數據傳輸時,為了節省空間流量,需要對數據或文件進行壓縮。在這裡我們講述 通過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
四、後續
如有其他更好的壓縮方法,請指出。後續會更新至此。