Zlib放气输入大于原始输入字符串的字符?

时间:2017-05-15 17:27:45

标签: c++ compression zlib

我对zlib压缩类型为char的字符串的输入感到有些困惑。下面我将代码的输出发布,我注意到输入字符串与输出相比,字节数更短

未压缩的大小为 8个字节 压缩为12 ?我没有正确看到这个吗?

这是代码。

#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <iostream>
#include "zlib.h"

void print( char *array, int length)
{
    for(int index = 0; index < length; index++)
        std::cout<<array[index];

    std::cout<<std::endl;
}
void clear( char *array, int length)
{
    for(int index = 0; index < length; index++)
        array[index] = 0;
}
int main()
{
    const int length = 30;
    char a[length] = "HHHHHHH";
    char b[length] = "";
    char c[length] = "";

    print( a, length);

    std::cout<<std::endl;
    uLong ucompSize = strlen(a)+1; // "string" + NULL delimiter.
    std::cout<<"ucompSize: "<<ucompSize<<std::endl;
    uLong compSize = compressBound(ucompSize);
    std::cout<<"compSize: "<<compSize<<std::endl;
    std::cout<<std::endl;
    // Deflate
    compress((Bytef *)b, &compSize, (Bytef *)a, ucompSize);
    std::cout<<"ucompSize: "<<ucompSize<<std::endl;
    std::cout<<"compSize: "<<compSize<<std::endl;
    print( b, length);
    std::cout<<std::endl;
    // Inflate
    uncompress((Bytef *)c, &ucompSize, (Bytef *)b, compSize);
    std::cout<<"ucompSize: "<<ucompSize<<std::endl;
    std::cout<<"compSize: "<<compSize<<std::endl;
    print( c, length);

    return 0;
}

这是输出。

HHHHHHH

ucompSize: 8
compSize: 21

ucompSize: 8
compSize: 12
x��     ��

ucompSize: 8
compSize: 12
HHHHHHH

Process returned 0 (0x0)   execution time : 0.013 s
Press ENTER to continue.

3 个答案:

答案 0 :(得分:3)

这些字节中至少有六个是压缩流前面的两个魔术字节(标题),将其标识为zlib压缩文件,以及校验和的四个字节。不计算格式的开销最多会留下六个字节的压缩数据,这比输入流小。

有关文件格式的更多详细信息,请参阅RFC的§2.2。您可以使用xxdhexdump等工具来调查十六进制字节组,以确认输出流的哪些部分是开销,哪些是压缩数据。

答案 1 :(得分:2)

compress()函数使用zlib格式,它在原始压缩数据周围放置一个双字节头和四字节尾部。即使原始压缩数据小于原始字符串,您也将从包装器中获得六个字节。对于空字符串,根本没有字节,原始压缩数据是两个字节。因此,zlib流的最小大小为8个字节。八个重复输入字节可能导致原始压缩数据短至四个字节,因此最小zlib包装结果为十个字节。

通常,您需要更大的无损压缩输入才能生效。

答案 2 :(得分:-1)

如果您想避免这种情况,可以使用compressBound()功能检查尺寸是否实际大于当前数据:

  

ZEXTERN uLong ZEXPORT compressBound OF((uLong sourceLen));
  compressBound()返回压缩后大小的上限   在compress()字节上compress2()sourceLen。它将在以前使用   compress()compress2()调用以分配目标缓冲区。