LZMA压缩解压

       这里介绍的是如何使用开源的LZMA压缩解压算法库。

       下载地址:http://tukaani.org/xz/

       里面有头文件、动态库和文档。里面有例子程序,是压缩和解压文件的,我试用过,可以。我这里介绍压缩buff到另一个buff中,这样可以实现边接受来自网络的数据,边写压缩文件。

      

#include "stdafx.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <assert.h>

#define LZMA_API_STATIC
#include "lzma.h"

#define LZMA_PRESET_VAL 0

static uint32_t
get_preset()
{
    return LZMA_PRESET_VAL | LZMA_PRESET_EXTREME;
}


static bool
get_error(lzma_ret ret)
{
    // Return successfully if the initialization went fine.
    if (ret == LZMA_OK | LZMA_STREAM_END)
        return true;

    // Something went wrong. The possible errors are documented in
    // lzma/container.h (src/liblzma/api/lzma/container.h in the source
    // package or e.g. /usr/include/lzma/container.h depending on the
    // install prefix).
    const char *msg;
    switch (ret) {
    case LZMA_MEM_ERROR:
        msg = "Memory allocation failed";
        break;

    case LZMA_OPTIONS_ERROR:
        msg = "Specified preset is not supported";
        break;

    case LZMA_UNSUPPORTED_CHECK:
        msg = "Specified integrity check is not supported";
        break;

    default:
        // This is most likely LZMA_PROG_ERROR indicating a bug in
        // this program or in liblzma. It is inconvenient to have a
        // separate error message for errors that should be impossible
        // to occur, but knowing the error code is important for
        // debugging. That's why it is good to print the error code
        // at least when there is no good error message to show.
        msg = "Unknown error, possibly a bug";
        break;
    }

    fprintf(stderr, "Error initializing the encoder: %s (error code %u)\n",
            msg, ret);
    return false;
}

static bool
init_encoder(lzma_stream *strm, uint32_t preset)
{
    // Initialize the encoder using a preset. Set the integrity to check
    // to CRC64, which is the default in the xz command line tool. If
    // the .xz file needs to be decompressed with XZ Embedded, use
    // LZMA_CHECK_CRC32 instead.
    lzma_ret ret = lzma_easy_encoder(strm, preset, LZMA_CHECK_CRC64);

    return get_error(ret);
}

static bool
init_decoder(lzma_stream *strm)
{
    // Initialize a .xz decoder. The decoder supports a memory usage limit
    // and a set of flags.
    //
    // The memory usage of the decompressor depends on the settings used
    // to compress a .xz file. It can vary from less than a megabyte to
    // a few gigabytes, but in practice (at least for now) it rarely
    // exceeds 65 MiB because that's how much memory is required to
    // decompress files created with "xz -9". Settings requiring more
    // memory take extra effort to use and don't (at least for now)
    // provide significantly better compression in most cases.
    //
    // Memory usage limit is useful if it is important that the
    // decompressor won't consume gigabytes of memory. The need
    // for limiting depends on the application. In this example,
    // no memory usage limiting is used. This is done by setting
    // the limit to UINT64_MAX.
    //
    // The .xz format allows concatenating compressed files as is:
    //
    //     echo foo | xz > foobar.xz
    //     echo bar | xz >> foobar.xz
    //
    // When decompressing normal standalone .xz files, LZMA_CONCATENATED
    // should always be used to support decompression of concatenated
    // .xz files. If LZMA_CONCATENATED isn't used, the decoder will stop
    // after the first .xz stream. This can be useful when .xz data has
    // been embedded inside another file format.
    //
    // Flags other than LZMA_CONCATENATED are supported too, and can
    // be combined with bitwise-or. See lzma/container.h
    // (src/liblzma/api/lzma/container.h in the source package or e.g.
    // /usr/include/lzma/container.h depending on the install prefix)
    // for details.
    lzma_ret ret = lzma_stream_decoder(
            strm, UINT64_MAX, LZMA_CONCATENATED);

    return get_error(ret);
}

static bool
do_lzma_code(lzma_stream *strm, const unsigned char *in_buff,const int in_size, unsigned char *out_buff, int & out_size)
{
    lzma_action action = LZMA_FINISH;

    uint8_t outbuf[BUFSIZ];

    strm->next_out = outbuf;
    strm->avail_out = sizeof(outbuf);

    strm->next_in = in_buff;
    strm->avail_in = in_size;

    lzma_ret ret = lzma_code(strm, action);

    out_size = sizeof(outbuf) - strm->avail_out;
    memcpy(out_buff,outbuf,out_size);

    return get_error(ret);
}

void 
wang_compress(const unsigned char *in_buff,const int in_size, unsigned char *out_buff, int & out_size)
{
    uint32_t preset = get_preset();
    lzma_stream strm = LZMA_STREAM_INIT;

    bool success = init_encoder(&strm, preset);
    if (success)
    {
        success = do_lzma_code(&strm, in_buff,in_size,out_buff, out_size);
    }

    lzma_end(&strm);
}
void 
wang_decompress(const unsigned char *in_buff,const int in_size, unsigned char *out_buff, int & out_size)
{
    lzma_stream strm = LZMA_STREAM_INIT;
    bool success = true;

    if (!init_decoder(&strm)) {
            // Decoder initialization failed. There's no point
            // to retry it so we need to exit.
        success = false;
    }

    success &= do_lzma_code(&strm,in_buff,in_size,out_buff,out_size);

    lzma_end(&strm);
}

int _tmain(int argc, _TCHAR* argv[])
{
    const unsigned char  const_string_value[] = "wjfsjfsjfojsofjsojrhghfgehoiheighehgehgieghhgohg osjfi`, sk;f;'l";

    std::cout<<const_string_value<<std::endl;

    const int const_string_size = strlen((const char*)const_string_value);

    std::cout<<const_string_size<<std::endl;

    unsigned char buff[1024] = {0};

    int size = 0;

    wang_compress(const_string_value,const_string_size,buff,size);


    std::cout<<size<<std::endl;

    unsigned char out_string_value[1024]={0};
    int out_string_size = 0;

    wang_decompress(buff,size,out_string_value,out_string_size);

    assert(out_string_size == const_string_size);

    std::cout<<out_string_value<<std::endl;
    std::cout<<const_string_size<<std::endl;

    std::cin>>out_string_size;
}

        最后测试程序证明,可以。

      

posted @ 2014-03-15 17:46  王程根的技术博客  阅读(8803)  评论(1编辑  收藏  举报