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
{
///
/// 输入缓冲区指针
///
public IntPtr next_in;
///
/// 输入缓冲去可用数据长度
///
public int avail_in;
///
/// 总输入字节数
///
public int total_in;
///
/// 输出缓冲区指针
///
public IntPtr next_out;
///
/// 输出缓冲可用长度
///
public int avail_out;
///
/// 总输出字节数
///
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;
}
///
/// 压缩数据
///
/// 压缩数据流
///
///
[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);
///
/// 这个函数在一些版本中不带下划线
///
/// 流对象
///
/// Zlib版本
/// 流对象大小
///
[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));
}
///
/// 压缩数据
///
/// 压缩后的数据缓冲
/// 压缩后的数据缓冲长度
/// 压缩前的数据缓冲
/// 压缩前的数据缓冲长度
///
[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);
///
/// 压缩数据
///
/// 压缩数据块
///
/// 压缩后的数据
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();
}
///
/// 解压数据
///
/// 解压后的数据缓冲
/// 解压后的数据缓冲长度
/// 压缩的数据缓冲
/// 压缩的数据缓冲长度
///
[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);
///
/// 解压数据
///
/// 压缩的数据缓冲
/// 解压后的数据
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();
}
}
}