//==============================================================
//  版权所有：深圳杰文科技
//  文件名：GZip.cs
//  版本：V1.0  
//  创建者：Jay  ( QQ： 85363208 )
//  创建时间：2017-11-28 16:18
//  创建描述：
//  修改者：
//  修改时间：
//  修改说明： 
//==============================================================

using System;
using System.IO;
using System.IO.Compression;
using System.Runtime.Serialization.Formatters.Binary;

namespace Infrastructure.Utilities
{
	public class GZip
	{
		public static byte[] Compress(object obj)
		{
			using (MemoryStream ms = new MemoryStream())
			{
				BinaryFormatter formatter = new BinaryFormatter();
				formatter.Serialize(ms, obj);
				byte[] bytes = ms.GetBuffer();
				bytes = GZip.Compress(bytes);
				return bytes;
			}
		}

		public static T Decompress<T>(byte[] data)
		{
			byte[] bytes = GZip.Decompress(data);
			using (MemoryStream ms = new MemoryStream(bytes))
			{
				BinaryFormatter formatter = new BinaryFormatter();
				object obj = formatter.Deserialize(ms);
				return (T)obj;
			}
		}

		public static byte[] Compress(byte[] data)
		{
			MemoryStream stream = new MemoryStream();
			GZipStream gZipStream = new GZipStream(stream, CompressionMode.Compress);
			gZipStream.Write(data, 0, data.Length);
			gZipStream.Close();
			return stream.ToArray();
		}

		public static byte[] Decompress(byte[] data)
		{
			MemoryStream stream = new MemoryStream();
			GZipStream gZipStream = new GZipStream(new MemoryStream(data), CompressionMode.Decompress);
			byte[] bytes = new byte[40960];
			int n;
			while ((n = gZipStream.Read(bytes, 0, bytes.Length)) != 0)
			{
				stream.Write(bytes, 0, n);
			}
			gZipStream.Close();
			return stream.ToArray();
		}

		public void CompressFile(string sourceFile, string destinationFile)
		{
			if (File.Exists(sourceFile) == false)
			{
				throw new FileNotFoundException();
			}

			byte[] buffer = null;
			FileStream sourceStream = null;
			FileStream destinationStream = null;
			GZipStream compressedStream = null;

			try
			{
				sourceStream = new FileStream(sourceFile, FileMode.Open, FileAccess.Read, FileShare.Read);

				buffer = new byte[sourceStream.Length];
				int checkCounter = sourceStream.Read(buffer, 0, buffer.Length);

				if (checkCounter != buffer.Length)
				{
					throw new ApplicationException();
				}

				destinationStream = new FileStream(destinationFile, FileMode.OpenOrCreate, FileAccess.Write);

				compressedStream = new GZipStream(destinationStream, CompressionMode.Compress, true);

				compressedStream.Write(buffer, 0, buffer.Length);
			}
			catch (ApplicationException ex)
			{
				throw new Exception(string.Format("压缩文件时发生错误：{0}", ex.Message));
			}
			finally
			{
				if (sourceStream != null)
				{
					sourceStream.Close();
				}

				if (compressedStream != null)
				{
					compressedStream.Close();
				}

				if (destinationStream != null)
				{
					destinationStream.Close();
				}
			}
		}

		public void DecompressFile(string sourceFile, string destinationFile)
		{
			if (File.Exists(sourceFile) == false)
			{
				throw new FileNotFoundException();
			}

			FileStream sourceStream = null;
			FileStream destinationStream = null;
			GZipStream decompressedStream = null;
			byte[] quartetBuffer = null;

			try
			{
				sourceStream = new FileStream(sourceFile, FileMode.Open);

				decompressedStream = new GZipStream(sourceStream, CompressionMode.Decompress, true);

				quartetBuffer = new byte[4];
				int position = (int)sourceStream.Length - 4;
				sourceStream.Position = position;
				sourceStream.Read(quartetBuffer, 0, 4);
				sourceStream.Position = 0;
				int checkLength = BitConverter.ToInt32(quartetBuffer, 0);

				byte[] buffer = new byte[checkLength + 100];

				int offset = 0;
				int total = 0;

				while (true)
				{
					int bytesRead = decompressedStream.Read(buffer, offset, 100);

					if (bytesRead == 0)
					{
						break;
					}

					offset += bytesRead;
					total += bytesRead;
				}

				destinationStream = new FileStream(destinationFile, FileMode.Create);
				destinationStream.Write(buffer, 0, total);

				destinationStream.Flush();
			}
			catch (ApplicationException ex)
			{
				throw new Exception(string.Format("解压文件时发生错误：{0}", ex.Message));
			}
			finally
			{
				if (sourceStream != null)
				{
					sourceStream.Close();
				}

				if (decompressedStream != null)
				{
					decompressedStream.Close();
				}

				if (destinationStream != null)
				{
					destinationStream.Close();
				}
			}

		}
	}
}
