using System;
using System.IO;
using System.Runtime.InteropServices;
namespace ConsoleApp1
{
/*
Zlib包装类,需要开启不安全代码编译
static void Main(string[] args)
{
byte[] src = Encoding.UTF8.GetBytes("Test");
byte[] dst = Zlib.compress(src);
byte[] temp = Zlib.uncompress(dst);
string t = Encoding.UTF8.GetString(temp);
Console.WriteLine(t);
Console.ReadKey();
}
*/
internal static class Zlib
{
[StructLayout(LayoutKind.Sequential)]
private struct z_stream
{
/// <summary>
/// 输入缓冲区指针
/// </summary>
public IntPtr next_in;
/// <summary>
/// 输入缓冲去可用数据长度
/// </summary>
public int avail_in;
/// <summary>
/// 总输入字节数
/// </summary>
public int total_in;
/// <summary>
/// 输出缓冲区指针
/// </summary>
public IntPtr next_out;
/// <summary>
/// 输出缓冲可用长度
/// </summary>
public int avail_out;
/// <summary>
/// 总输出字节数
/// </summary>
public int total_out;
public IntPtr msg;
public IntPtr state;
public IntPtr zalloc;
public IntPtr zfree;
public IntPtr opaque;
public int data_type;
public uint adler;
public uint reserved;
}
/// <summary>
/// 压缩数据
/// </summary>
/// <param name="stream">压缩数据流</param>
/// <param name="flush"></param>
/// <returns></returns>
[DllImport("zlib1.dll", EntryPoint = "deflate", CallingConvention = CallingConvention.Cdecl)]
private static extern int deflate(ref z_stream stream, int flush = 4);
[DllImport("zlib1.dll", EntryPoint = "inflate", CallingConvention = CallingConvention.Cdecl)]
private static extern int inflate(ref z_stream stream, int flush = 4);
[DllImport("zlib1.dll", EntryPoint = "zlibVersion", CallingConvention = CallingConvention.Cdecl)]
private static extern IntPtr zlibVersion();
[DllImport("zlib1.dll", EntryPoint = "deflateEnd", CallingConvention = CallingConvention.Cdecl)]
private static extern IntPtr deflateEnd(ref z_stream stream);
[DllImport("zlib1.dll", EntryPoint = "inflateEnd", CallingConvention = CallingConvention.Cdecl)]
private static extern IntPtr inflateEnd(ref z_stream stream);
/// <summary>
/// 这个函数在一些版本中不带下划线
/// </summary>
/// <param name="stream">流对象</param>
/// <param name="level"></param>
/// <param name="version">Zlib版本</param>
/// <param name="nSize">流对象大小</param>
/// <returns></returns>
[DllImport("zlib1.dll", EntryPoint = "deflateInit_", CallingConvention = CallingConvention.Cdecl)]
private static extern int deflateInit(ref z_stream stream, int level, IntPtr version, int nSize);
private static int deflateInit(ref z_stream stream, int level = -1)
{
return deflateInit(ref stream, level, zlibVersion(), Marshal.SizeOf(stream));
}
[DllImport("zlib1.dll", EntryPoint = "inflateInit_", CallingConvention = CallingConvention.Cdecl)]
private static extern int inflateInit(ref z_stream stream, IntPtr version, int nSize);
private static int inflateInit(ref z_stream stream)
{
return inflateInit(ref stream, zlibVersion(), Marshal.SizeOf(stream));
}
/// <summary>
/// 压缩数据
/// </summary>
/// <param name="dest">压缩后的数据缓冲</param>
/// <param name="destLen">压缩后的数据缓冲长度</param>
/// <param name="source">压缩前的数据缓冲</param>
/// <param name="sourceLen">压缩前的数据缓冲长度</param>
/// <returns></returns>
[DllImport("zlib1.dll", EntryPoint = "compress", CallingConvention = CallingConvention.Cdecl)]
public static extern int compress([MarshalAs(UnmanagedType.LPArray)] byte[] dest, out int destLen,
[MarshalAs(UnmanagedType.LPArray)] byte[] source, int sourceLen);
/// <summary>
/// 压缩数据
/// </summary>
/// <param name="src">压缩数据块</param>
/// <param name="flush"></param>
/// <returns>压缩后的数据</returns>
public static byte[] compress(byte[] src)
{
var stream = new z_stream();
var ret = new MemoryStream();
deflateInit(ref stream);
unsafe
{
byte[] dst = new byte[4096];
fixed (byte* psrc = src, pdst = dst)
{
stream.avail_in = src.Length;
stream.next_in = new IntPtr(psrc);
while (true)
{
stream.avail_out = dst.Length;
stream.next_out = new IntPtr(pdst);
deflate(ref stream, 4);
if (stream.avail_out == dst.Length)
{
break;
}
ret.Write(dst, 0, dst.Length - stream.avail_out);
}
}
}
deflateEnd(ref stream);
return ret.ToArray();
}
/// <summary>
/// 解压数据
/// </summary>
/// <param name="dest">解压后的数据缓冲</param>
/// <param name="destLen">解压后的数据缓冲长度</param>
/// <param name="source">压缩的数据缓冲</param>
/// <param name="sourceLen">压缩的数据缓冲长度</param>
/// <returns></returns>
[DllImport("zlib1.dll", EntryPoint = "uncompress", CallingConvention = CallingConvention.Cdecl)]
public static extern int uncompress([MarshalAs(UnmanagedType.LPArray)] byte[] dest, out int destLen,
[MarshalAs(UnmanagedType.LPArray)] byte[] source, int sourceLen);
/// <summary>
/// 解压数据
/// </summary>
/// <param name="src">压缩的数据缓冲</param>
/// <returns>解压后的数据</returns>
public static byte[] uncompress(byte[] src)
{
var stream = new z_stream();
var ret = new MemoryStream();
inflateInit(ref stream);
unsafe
{
byte[] dst = new byte[4096];
fixed (byte* psrc = src, pdst = dst)
{
stream.avail_in = src.Length;
stream.next_in = new IntPtr(psrc);
while (true)
{
stream.avail_out = dst.Length;
stream.next_out = new IntPtr(pdst);
inflate(ref stream, 4);
if (stream.avail_out == dst.Length)
{
break;
}
ret.Write(dst, 0, dst.Length - stream.avail_out);
}
}
}
inflateEnd(ref stream);
return ret.ToArray();
}
}
}