我对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.
答案 0 :(得分:3)
这些字节中至少有六个是压缩流前面的两个魔术字节(标题),将其标识为zlib压缩文件,以及校验和的四个字节。不计算格式的开销最多会留下六个字节的压缩数据,这比输入流小。
有关文件格式的更多详细信息,请参阅RFC的§2.2。您可以使用xxd
或hexdump
等工具来调查十六进制字节组,以确认输出流的哪些部分是开销,哪些是压缩数据。
答案 1 :(得分:2)
compress()
函数使用zlib格式,它在原始压缩数据周围放置一个双字节头和四字节尾部。即使原始压缩数据小于原始字符串,您也将从包装器中获得六个字节。对于空字符串,根本没有字节,原始压缩数据是两个字节。因此,zlib流的最小大小为8个字节。八个重复输入字节可能导致原始压缩数据短至四个字节,因此最小zlib包装结果为十个字节。
通常,您需要更大的无损压缩输入才能生效。
答案 2 :(得分:-1)
如果您想避免这种情况,可以使用compressBound()
功能检查尺寸是否实际大于当前数据:
ZEXTERN uLong ZEXPORT compressBound OF((uLong sourceLen));
compressBound()
返回压缩后大小的上限 在compress()
字节上compress2()
或sourceLen
。它将在以前使用compress()
或compress2()
调用以分配目标缓冲区。