返回> 网站首页 

zlib.h使用概述

yoours2016-05-13 13:15:13 阅读 2290

简介一边听听音乐,一边写写文章。

一、下载地址
http://www.zlib.net/

二、库解析

ZEXTERN const char * ZEXPORT zlibVersion OF((void));

这里的OF其实就是zconf里的一个定义:

#ifndef OF
 ifdef STDC
   define OF(args)  args
 else
   define OF(args)  ()
 endif
#endif

大概意思就是用在参数列表前面,有什么作用?不了解,不明白。

ZEXTERN就是extern,ZEXPORT的作用不明白,不了解

 

ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level));

为压缩初始化流状态,level必须设置为Z_DEFAULT_COMPRESSION(-1)或者0~9。

 调用deflateInit之前,strm的zalloc, zfree , opaque必须被初始化

返回值:Z_OK 成功

        Z_MEM_ERROR 内存不足

        Z_STREAM_ERROR level没设对

        Z_VERSION_ERROR 版本不匹配

ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush));

压缩尽可能多的输入数据,input缓存空了或者output缓存满了时停止。

就是说,每次读入的输入数据尽可能多,但每次的输出数据都正好将输出缓冲区填满(最后一次除外,可能填不满)

如果没有强制flush,该函数会有输出“延迟”,即读入输入,但却没有产生任何输出

返回值:Z_OK 压缩了更多的输入数据(相比之前)或者产生了更多的输出(相比之前)

        Z_STREAM_END 输入已读完,而且如果设置了Z_FINISH的话,所有输出都会产生

        Z_STREAM_ERROR 流状态不对,如next_in或next_out为Z_NULL

        Z_BUF_ERROR 无法执行任何操作,如avail_in或avail_out为0,这并不是一个致命错误,可以提供更多输入或分配更多输出缓存,然后再次调用deflate

ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm));

结束压缩过程,为该stream动态分配的所有内存被释放,未处理的输入被丢弃,未输出的输出(输出延迟所致)也被丢弃

返回值:

        Z_OK 成功

        Z_STREAM_ERROR 流状态不一致

ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm));

为解压初始化流状态

 调用inflateInit 之前,strm的next_in, avail_in, zalloc, zfree , opaque必须被初始化(比deflateInit多了next_in和avail_in)

返回值:Z_OK 成功

        Z_MEM_ERROR 内存不足

        Z_STREAM_ERROR 流不对,如strm为NULL

        Z_VERSION_ERROR 版本不匹配

ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush));

解压尽量多的输入数据,input缓存空了或者output缓存满了时停止。

就是说,每次读入的输入数据尽可能多,但每次的输出数据都正好将输出缓冲区填满(最后一次除外,可能填不满)

如果没有强制flush,该函数会有输出“延迟”,即读入输入,但却没有产生任何输出

返回值:Z_OK 解压了更多的输入数据(相比之前)或者产生了更多的输出(相比之前)

        Z_STREAM_END 输入已读完,而且所有输出都产生了(这里没提到Z_FINISH)

        Z_STREAM_ERROR 流状态不对,如next_in或next_out为Z_NULL

        Z_NEED_DICT 需要预置词典

        Z_MEM_ERROR 内存不足

        Z_DATA_ERROR 输入数据不合zlib规范或者校验错误 

        Z_BUF_ERROR 无法执行任何操作,如avail_in或avail_out为0,这并不是一个致命错误,可以提供更多输入或分配更多输出缓存,然后再次调用inflate
ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm));

结束解压过程,为该stream动态分配的所有内存被释放,未处理的输入被丢弃,未输出的输出(输出延迟所致)也被丢弃

返回值:Z_OK 成功

        Z_STREAM_ERROR 流状态不一致

ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm,
                                     int  level,
                                     int  method,
                                     int  windowBits,
                                     int  memLevel,
                                     int  strategy));

目前版本method参数必须设为Z_DEFLATED

windowBits参数是窗口大小以2为底求的对数(历史缓冲区的大小)。目前版本应在8~15之间,值越大,将耗费更多的内存,同时带来更好的压缩结果。如果使用deflateInit,默认的windowBits是15.

windowBits也可以置为-15~-8,表示要进行的是原始压缩,-windowBits值决定了窗口大小。接下来deflate将产生无zlib头部和尾部的原始压缩数据,也不会计算adler32校验值。

如果要进行gzip压缩,windowBits也可以比15大。windowBits置为16将在压缩后的数据前后加上gzip头部和尾部,而不是zlib的头尾部。

memLevel为1~9,数值越大,the internal compression state(什么意思?不知道)占用的内存也越大,但是速度也越快。默认为8

strategy用于调整压缩算法,一般置为Z_DEFAULT_STRATEGY

返回值:

       Z_OK 成功

       Z_MEM_ERROR内存不足

       Z_STREAM_ERROR某个参数非法

       Z_VERSION_ERROR版本不匹配

 

ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm,

                                     int  windowBits));

windowBits参数是窗口大小以2为底求的对数(历史缓冲区的大小)。目前版本应在8~15之间,值越大,将耗费更多的内存,同时带来更好的压缩结果。如果使用inflateInit,默认的windowBits是15.

windowBits也可以置为0,以使用经zlib压缩的流(即strm)头部中的window size

windowBits也可以置为-15~-8,表示要进行的是原始解压,-windowBits值决定了窗口大小。不寻找zlib或gzip头部,不产生校验值,不在输入流尾寻找任何校验值。该方法用于解压其它利用了deflate压缩方法的格式,如zip。这些格式有自己的校验值。

windowBits也可以比15大,以进行gzip解压。在windowBits(指的是原来的8~15或者-15~-8)上加上32来自动识别zlib和gzip(所以要解压http中的gzip部分,一般是置为15+32=47)。或者在windowBits上加上16,仅解码gzip格式,此时zlib格式会返回Z_DATA_ERROR。如果解压的是gzip,strm->adler是crc32校验,而不是adler32

返回值:

        Z_OK 成功

 

       Z_MEM_ERROR内存不足

       Z_STREAM_ERROR某个参数非法

       Z_VERSION_ERROR版本不匹配


三、压缩生成文件

#include <stdio.h>

#include "zlib.h"


int main()

{

  char *data = "this is a gzip test from NinGoo.net";

  gzFile *fp=NULL;

  fp=gzopen("test_out.gz","wb");

  gzwrite(fp,data,strlen(data));

  gzclose(fp);

}


四、内存解压缩

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <errno.h>

#include <zlib.h>

/* Compress data */

int zcompress(Bytef *data, uLong ndata, 

Bytef *zdata, uLong *nzdata)

{

z_stream c_stream;

int err = 0;


if(data && ndata > 0)

{

c_stream.zalloc = (alloc_func)0;

c_stream.zfree = (free_func)0;

c_stream.opaque = (voidpf)0;

if(deflateInit(&c_stream, Z_DEFAULT_COMPRESSION) != Z_OK) return -1;

c_stream.next_in  = data;

c_stream.avail_in  = ndata;

c_stream.next_out = zdata;

c_stream.avail_out  = *nzdata;

while (c_stream.avail_in != 0 && c_stream.total_out < *nzdata) 

{

if(deflate(&c_stream, Z_NO_FLUSH) != Z_OK) return -1;

}

        if(c_stream.avail_in != 0) return c_stream.avail_in;

for (;;) {

if((err = deflate(&c_stream, Z_FINISH)) == Z_STREAM_END) break;

if(err != Z_OK) return -1;

}

if(deflateEnd(&c_stream) != Z_OK) return -1;

*nzdata = c_stream.total_out;

return 0;

}

return -1;

}


/* Compress gzip data */

int gzcompress(Bytef *data, uLong ndata, 

Bytef *zdata, uLong *nzdata)

{

z_stream c_stream;

int err = 0;


if(data && ndata > 0)

{

c_stream.zalloc = (alloc_func)0;

c_stream.zfree = (free_func)0;

c_stream.opaque = (voidpf)0;

if(deflateInit2(&c_stream, Z_DEFAULT_COMPRESSION, Z_DEFLATED, 

                    /*-MAX_WBITS*/MAX_WBITS+16, 8, Z_DEFAULT_STRATEGY) != Z_OK) return -1;

c_stream.next_in  = data;

c_stream.avail_in  = ndata;

c_stream.next_out = zdata;

c_stream.avail_out  = *nzdata;

while (c_stream.avail_in != 0 && c_stream.total_out < *nzdata) 

{

if(deflate(&c_stream, Z_NO_FLUSH) != Z_OK) return -1;

}

        if(c_stream.avail_in != 0) return c_stream.avail_in;

for (;;) {

if((err = deflate(&c_stream, Z_FINISH)) == Z_STREAM_END) break;

if(err != Z_OK) return -1;

}

if(deflateEnd(&c_stream) != Z_OK) return -1;

*nzdata = c_stream.total_out;

return 0;

}

return -1;

}


/* Uncompress data */

int zdecompress(Byte *zdata, uLong nzdata,                 

        Byte *data, uLong *ndata)

{

int err = 0;

z_stream d_stream; /* decompression stream */


d_stream.zalloc = (alloc_func)0;

d_stream.zfree = (free_func)0;

d_stream.opaque = (voidpf)0;

    d_stream.next_in  = zdata;

d_stream.avail_in = 0;

d_stream.next_out = data;

if(inflateInit(&d_stream) != Z_OK) return -1;

while (d_stream.total_out < *ndata && d_stream.total_in < nzdata) {

d_stream.avail_in = d_stream.avail_out = 1; /* force small buffers */

if((err = inflate(&d_stream, Z_NO_FLUSH)) == Z_STREAM_END) break;

if(err != Z_OK) return -1;

}

if(inflateEnd(&d_stream) != Z_OK) return -1;

*ndata = d_stream.total_out;

return 0;

}


/* HTTP gzip decompress */

int httpgzdecompress(Byte *zdata, uLong nzdata,                 

        Byte *data, uLong *ndata)

{

    int err = 0;

    z_stream d_stream = {0}; /* decompression stream */

    static char dummy_head[2] = 

    {

        0x8 + 0x7 * 0x10,

        (((0x8 + 0x7 * 0x10) * 0x100 + 30) / 31 * 31) & 0xFF,

    };

    d_stream.zalloc = (alloc_func)0;

    d_stream.zfree = (free_func)0;

    d_stream.opaque = (voidpf)0;

    d_stream.next_in  = zdata;

    d_stream.avail_in = 0;

    d_stream.next_out = data;

    if(inflateInit2(&d_stream, 47) != Z_OK) return -1;

    while (d_stream.total_out < *ndata && d_stream.total_in < nzdata) {

        d_stream.avail_in = d_stream.avail_out = 1; /* force small buffers */

        if((err = inflate(&d_stream, Z_NO_FLUSH)) == Z_STREAM_END) break;

        if(err != Z_OK )

        {

            if(err == Z_DATA_ERROR)

            {

                d_stream.next_in = (Bytef*) dummy_head;

                d_stream.avail_in = sizeof(dummy_head);

                if((err = inflate(&d_stream, Z_NO_FLUSH)) != Z_OK) 

                {

                    return -1;

                }

            }

            else return -1;

        }

    }

    if(inflateEnd(&d_stream) != Z_OK) return -1;

    *ndata = d_stream.total_out;

    return 0;

}


/* Uncompress gzip data */

int gzdecompress(Byte *zdata, uLong nzdata,                 

        Byte *data, uLong *ndata)

{

    int err = 0;

    z_stream d_stream = {0}; /* decompression stream */

    static char dummy_head[2] = 

    {

        0x8 + 0x7 * 0x10,

        (((0x8 + 0x7 * 0x10) * 0x100 + 30) / 31 * 31) & 0xFF,

    };

    d_stream.zalloc = (alloc_func)0;

    d_stream.zfree = (free_func)0;

    d_stream.opaque = (voidpf)0;

    d_stream.next_in  = zdata;

    d_stream.avail_in = 0;

    d_stream.next_out = data;

    if(inflateInit2(&d_stream, -MAX_WBITS) != Z_OK) return -1;

    //if(inflateInit2(&d_stream, 47) != Z_OK) return -1;

    while (d_stream.total_out < *ndata && d_stream.total_in < nzdata) {

        d_stream.avail_in = d_stream.avail_out = 1; /* force small buffers */

        if((err = inflate(&d_stream, Z_NO_FLUSH)) == Z_STREAM_END) break;

        if(err != Z_OK )

        {

            if(err == Z_DATA_ERROR)

            {

                d_stream.next_in = (Bytef*) dummy_head;

                d_stream.avail_in = sizeof(dummy_head);

                if((err = inflate(&d_stream, Z_NO_FLUSH)) != Z_OK) 

                {

                    return -1;

                }

            }

            else return -1;

        }

    }

    if(inflateEnd(&d_stream) != Z_OK) return -1;

    *ndata = d_stream.total_out;

    return 0;

}


#define BUF_SIZE 65535

int main()

{

char *data = "kjdalkfjdflkjdlkfjdklfjdlkfjlkdjflkdjflddajfkdjfkdfaskf;ldsfk;ldakf;ldskfl;dskf;ld";

uLong ndata = strlen(data);

Bytef zdata[BUF_SIZE];

uLong nzdata = BUF_SIZE;

Bytef  odata[BUF_SIZE];

uLong nodata = BUF_SIZE;

memset(zdata, 0, BUF_SIZE);

//if(zcompress((Bytef *)data, ndata, zdata, &nzdata) == 0)

if(gzcompress((Bytef *)data, ndata, zdata, &nzdata) == 0)

{

fprintf(stdout, "nzdata:%d %s\n", nzdata, zdata);

memset(odata, 0, BUF_SIZE);

//if(zdecompress(zdata, ndata, odata, &nodata) == 0)

if(gzdecompress(zdata, ndata, odata, &nodata) == 0)

{

fprintf(stdout, "%d %s\n", nodata, odata);

}

}

}


windowBits

-MAX_WBITS 不生成gz头

MAX_WBITS+16 生成gz头


C#代码

/// <summary>

        /// 压缩数据流

        /// </summary>

        /// <param name="buffer"></param>

        /// <param name="encode"></param>

        /// <param name="key"></param>

        /// <returns></returns>

        public static string GZipCompress(string buffer, System.Text.Encoding encode)

        {

            string strs = "";

            try

            {

                if (buffer != null && buffer.Length > 0)

                {

                    byte[] temp = encode.GetBytes(buffer);

                    using (MemoryStream msTemp = new MemoryStream())

                    {

                        using (GZipStream gz = new GZipStream(msTemp, CompressionMode.Compress, true))

                        {

                            gz.Write(temp, 0, temp.Length);

                            gz.Close();

                        }

                        msTemp.Seek(0, SeekOrigin.Begin);

                        msTemp.Flush();

                        temp = new byte[msTemp.Length];

                        msTemp.Read(temp, 0, (int)msTemp.Length);

                        strs = HexToStr(temp);

                    }

                }

            }

            catch

            {


            }

            return strs;

        }


        /// <summary>

        /// 解压

        /// </summary>

        /// <param name="str_buffer"></param>

        /// <param name="encode"></param>

        /// <returns></returns>

        public static string GZipDecompress(string str_buffer, System.Text.Encoding encode)

        {

            try

            {

                byte[] buffer = StrToHex(str_buffer);

                if (buffer.Length > 0)

                {

                    byte[] temp;

                    using (MemoryStream msTemp = new MemoryStream(buffer))

                    {

                        using (MemoryStream msOutTemp = new MemoryStream())

                        {

                            using (GZipStream gz = new GZipStream(msTemp, CompressionMode.Decompress, true))

                            {

                                gz.CopyTo(msOutTemp);

                            }

                            msOutTemp.Seek(0, SeekOrigin.Begin);

                            msOutTemp.Flush();

                            temp = new byte[msOutTemp.Length];

                            msOutTemp.Read(temp, 0, temp.Length);

                        }

                        return encode.GetString(temp, 0, temp.Length);

                    }

                }

                else

                {

                    return "";

                }

            }

            catch (Exception ex)

            {

                string s = ex.Message;

                return "";

            }

        }


微信小程序扫码登陆

文章评论

2290人参与,0条评论