.net 利用 GZipStream 压缩和解压缩

时间:2023-03-09 04:14:45
.net 利用 GZipStream 压缩和解压缩

1.GZipStream 类

此类在 .NET Framework 2.0 版中是新增的。

提供用于压缩和解压缩流的方法和属性

2.压缩byte[]

  1. /// <summary>
  2. /// 压缩数据
  3. /// </summary>
  4. /// <param name="data"></param>
  5. /// <returns></returns>
  6. public byte[] Compress(byte[] data)
  7. {
  8. MemoryStream ms = new MemoryStream();
  9. GZipStream zipStream = new GZipStream(ms, CompressionMode.Compress);
  10. zipStream.Write(data, 0, data.Length);//将数据压缩并写到基础流中
  11. zipStream.Close();
  12. return ms.ToArray();
  13. }

3.解压byte[]

  1. /// 解压数据
  2. /// </summary>
  3. /// <param name="data"></param>
  4. /// <returns></returns>
  5. public byte[] Decompress(byte[] data)
  6. {
  7. MemoryStream srcMs = new MemoryStream(data);
  8. GZipStream zipStream = new GZipStream(srcMs, CompressionMode.Decompress);
  9. MemoryStream ms = new MemoryStream();
  10. byte[] bytes = new byte[40960];
  11. int n;
  12. while ((n = zipStream.Read(bytes, 0, bytes.Length)) > 0)
  13. {
  14. ms.Write(bytes, 0, n);
  15. }
  16. zipStream.Close();
  17. return ms.ToArray();
  18. }

4.压缩byte[]数据,存放到文件中

  1. /// <summary>
  2. /// 将指定的字节数组压缩,并写入到目标文件
  3. /// </summary>
  4. /// <param name="srcBuffer">指定的源字节数组</param>
  5. /// <param name="destFile">指定的目标文件</param>
  6. public static void CompressData(byte[] srcBuffer, string destFile)
  7. {
  8. FileStream destStream = null;
  9. GZipStream compressedStream = null;
  10. try
  11. {
  12. //打开文件流
  13. destStream = new FileStream(destFile, FileMode.OpenOrCreate, FileAccess.Write);
  14. //指定压缩的目的流(这里是文件流)
  15. compressedStream = new GZipStream(destStream, CompressionMode.Compress, true);
  16. //往目的流中写数据,而流将数据写到指定的文件
  17. compressedStream.Write(srcBuffer, 0, srcBuffer.Length);
  18. }
  19. catch (Exception ex)
  20. {
  21. throw new Exception(String.Format("压缩数据写入文件{0}时发生错误", destFile), ex);
  22. }
  23. finally
  24. {
  25. // Make sure we allways close all streams
  26. if (null != compressedStream)
  27. {
  28. compressedStream.Close();
  29. compressedStream.Dispose();
  30. }
  31. if (null != destStream)
  32. destStream.Close();
  33. }
  34. }

5.解压文件,得到byte[]数据

  1. /// <summary>
  2. /// 将指定的文件解压,返回解压后的数据
  3. /// </summary>
  4. /// <param name="srcFile">指定的源文件</param>
  5. /// <returns>解压后得到的数据</returns>
  6. public static byte[] DecompressData(string srcFile)
  7. {
  8. if (false == File.Exists(srcFile))
  9. throw new FileNotFoundException(String.Format("找不到指定的文件{0}", srcFile));
  10. FileStream sourceStream = null;
  11. GZipStream decompressedStream = null;
  12. byte[] quartetBuffer = null;
  13. try
  14. {
  15. sourceStream = new FileStream(srcFile, FileMode.Open, FileAccess.Read, FileShare.Read);
  16. decompressedStream = new GZipStream(sourceStream, CompressionMode.Decompress, true);
  17. // Read the footer to determine the length of the destiantion file
  18. //GZIP文件格式说明:
  19. //10字节的头,包含幻数、版本号以及时间戳
  20. //可选的扩展头,如原文件名
  21. //文件体,包括DEFLATE压缩的数据
  22. //8字节的尾注,包括CRC-32校验和以及未压缩的原始数据长度(4字节) 文件大小不超过4G
  23. //为Data指定byte的长度,故意开大byte数据的范围
  24. //读取未压缩的原始数据长度
  25. quartetBuffer = new byte[4];
  26. long position = sourceStream.Length - 4;
  27. sourceStream.Position = position;
  28. sourceStream.Read(quartetBuffer, 0, 4);
  29. int checkLength = BitConverter.ToInt32(quartetBuffer, 0);
  30. byte[] data;
  31. if (checkLength <= sourceStream.Length)
  32. {
  33. data = new byte[Int16.MaxValue];
  34. }
  35. else
  36. {
  37. data = new byte[checkLength + 100];
  38. }
  39. //每100byte从解压流中读出数据,并将读出的数据Copy到Data byte[]中,这样就完成了对数据的解压
  40. byte[] buffer = new byte[100];
  41. sourceStream.Position = 0;
  42. int offset = 0;
  43. int total = 0;
  44. while (true)
  45. {
  46. int bytesRead = decompressedStream.Read(buffer, 0, 100);
  47. if (bytesRead == 0)
  48. break;
  49. buffer.CopyTo(data, offset);
  50. offset += bytesRead;
  51. total += bytesRead;
  52. }
  53. //剔除多余的byte
  54. byte[] actualdata = new byte[total];
  55. for (int i = 0; i < total; i++)
  56. actualdata[i] = data[i];
  57. return actualdata;
  58. }
  59. catch (Exception ex)
  60. {
  61. throw new Exception(String.Format("从文件{0}解压数据时发生错误", srcFile), ex);
  62. }
  63. finally
  64. {
  65. if (sourceStream != null)
  66. sourceStream.Close();
  67. if (decompressedStream != null)
  68. decompressedStream.Close();
  69. }
  70. }

6.小结

压缩,解压都用GZipStream,操作的对象时普通流MemoryStream,不同的是:

压缩是将btye[]型的数据写入GZipStream中,而解压的时候是将GzipStream中的数据写入到byte[]中,并将读出的数据写入到MemoryStream后一次性输出

压缩到文件与压缩成byte[]不同的是压缩到文件利用到了FileStream将流写到文件,解压Gzip文件,需要根据文件的规则进行:后4位记录未压缩前的长度,根据该长度可以将解压出来的文件存放到稍大的byte[]中