zlib壓縮解壓

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <zlib.h>
#include <assert.h>
#define SIZE_CHUNK (8 * 1024)

 

static int __do_inflate_write(z_stream &strm,
        FILE *fp, void *data, size_t size)
{
    int res = -1;
    char out[SIZE_CHUNK];

    strm.next_in = (Bytef *)data;
    strm.avail_in = size;

    //printf("inflate: %u\n", strm.avail_in);

    /* run inflate() on input until output buffer not full */
    do {
        strm.avail_out = sizeof(out);
        strm.next_out  = (Bytef *)out;
        res = inflate(&strm, Z_NO_FLUSH);
        assert(res != Z_STREAM_ERROR);  /* state not clobbered */
        switch (res) {
            case Z_NEED_DICT:
                res = Z_DATA_ERROR;     /* and fall through */
            case Z_DATA_ERROR:
            case Z_MEM_ERROR:
                goto out;
        }

        size_t wlen = fwrite(out, 1, sizeof(out) - strm.avail_out, fp);
        assert(wlen == sizeof(out) - strm.avail_out);

        //printf("  write: %zu\n", wlen);
    } while (strm.avail_out == 0);

out:
    return res;
}


/***************************************************************************************
 *   Name: file_inflate
 *   Desc: Decompress from file source to file dest until stream ends or EOF.
 *  Input:
 * Output:
 * Return: Z_OK on success
 *         Z_MEM_ERROR     if memory could not be allocated for processing
 *         Z_DATA_ERROR    if the deflate data isinvalid or incomplete
 *         Z_VERSION_ERROR if the version of zlib.h and the version of
 *                            the library linked do not match
 *         Z_ERRNO         if there is an error reading or writing the files
 * Others: -
 ***************************************************************************************/
int file_inflate(const char *fsrc, const char *fdst)
{
    int res = -1;
    FILE *src = fopen(fsrc, "r");
    FILE *dst = fopen(fdst, "w+");
    assert(src && dst);

    z_stream strm = {Z_NULL};

    res = inflateInit(&strm);
    assert(res == Z_OK);

    /* decompress until deflate stream ends or end of file */
    do {
        char in[SIZE_CHUNK];
        size_t rlen = fread(in, 1, sizeof(in), src);
        if (rlen == 0) {
            printf("EOF\n");
            break;
        }

        /* done when inflate() says it's done */
        res = __do_inflate_write(strm, dst, in, rlen);
    } while (res != Z_STREAM_END);

    /* clean up and return */
    (void)inflateEnd(&strm);
    fclose(src);
    fclose(dst);
    return res == Z_STREAM_END ? Z_OK : Z_DATA_ERROR;
}

 

static void __do_deflate_write(z_stream &strm,
        FILE *fp, void *data, size_t size, int flush)
{
    char out[SIZE_CHUNK];

    strm.avail_in = size;
    strm.next_in = (Bytef *)data;
    //printf("deflate: %u\n", strm.avail_in);

    /*  run deflate() on input until output buffer not full, finish
     *  compression if all of source has been read in */
    do {
        strm.next_out = (Bytef *)out;
        strm.avail_out = sizeof(out);

        int res = deflate(&strm, flush);
        assert(res != Z_STREAM_ERROR);  // state not clobbered

        size_t wlen = fwrite(out, 1, sizeof(out) - strm.avail_out, fp);
        assert(wlen == sizeof(out) - strm.avail_out);

        //printf("  write: %zu\n", wlen);
    } while (strm.avail_out == 0); // 返回0,則表示正好out空間不夠大了

    assert(strm.avail_in == 0);     /* all input will be used */
}


/***************************************************************************************
 *   Name: file_deflate
 *   Desc: Compress from file source to file dest until EOF on source
 *  Input:
 *         @fname - source file name
 * Output:
 * Return: Z_OK on success
 *         Z_MEM_ERROR     if memory could not be allocated for processing
 *         Z_STREAM_ERROR  if an invalid compression level is supplied
 *         Z_VERSION_ERROR if the version of zlib.h and the version of
 *                            the library linked do not match
 *         Z_ERRNO         if there is an error reading or writing the files
 * Others: -
 ***************************************************************************************/
int file_deflate(const char *fsrc, const char *fdst)
{
    int res = -1;
    int flush = Z_NO_FLUSH;

    FILE *src = fopen(fsrc, "r");
    FILE *dst = fopen(fdst, "w+");
    assert(src && dst);

    z_stream strm = {Z_NULL};

    res = deflateInit(&strm, Z_DEFAULT_COMPRESSION);
    assert(res == Z_OK);

    /* Compress until end of file */
    do {
        char in[SIZE_CHUNK];
        size_t rlen = fread(in, 1, sizeof(in), src);
        if (rlen == 0) {
            printf("EOF\n");
            break;
        }
        // 這裏需要區分文件尾或者文件中間
        flush = feof(src) ? Z_FINISH : Z_NO_FLUSH;
        __do_deflate_write(strm, dst, in, rlen, flush);

    } while (flush != Z_FINISH);

    /* clean up and return */
    (void)deflateEnd(&strm);

    fclose(src);
    fclose(dst);
    return Z_OK;
}


int main(int argc, char *argv[])
{
        int res = -1;

        if (argv[1] && argv[2] && argv[3] && 0 == strcmp(argv[1], "-d")) {
                /* -d模式 表示壓縮文件 */
                res = file_deflate(argv[2], argv[3]);
        }
        else if (argv[1] && argv[2]) {
                /* 解壓文件 */
                res = file_inflate(argv[1], argv[2]);
        }
        else {
                printf("%s [ -d[mean compress]] < source > < dest >\n", argv[0]);
        printf("or %s < source > < dest >\n", argv[0]);
                exit(EXIT_FAILURE);
        }

        printf("Result:\t\t\t\t[%s]\n", res ? "Failure" : "Success");
        exit(res ? EXIT_FAILURE : EXIT_SUCCESS);
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章