deflate是一种使用了LZ77算法与哈夫曼编码(Huffman Coding)实现的无损数据压缩算法。它是一个无专利的,可以自由使用的算法。
gizp是一种以0x1F8B标志开头的数据格式,其内部通常采用DEFLATE算法对数据进行压缩。
下面附上基于zlib库实现的gzip数据压缩和解压缩函数:
//gzip解压缩 std::string decompress(const std::string &raw) { z_stream inflate_stream; memset(&inflate_stream, 0, sizeof(inflate_stream)); // TODO: reuse z_streams if (deflateInit2(&deflate_stream, Z_DEFAULT_COMPRESSION, Z_DEFLATED, MAX_WBITS + 16, 8, Z_DEFAULT_STRATEGY) != Z_OK) { throw std::runtime_error("failed to initialize inflate"); } inflate_stream.next_in = reinterpret_cast<Bytef *>(const_cast<char *>(raw.data())); inflate_stream.avail_in = uInt(raw.size()); std::string result; char out[15384]; int code; do { inflate_stream.next_out = reinterpret_cast<Bytef *>(out); inflate_stream.avail_out = sizeof(out); code = inflate(&inflate_stream, 0); // result.append(out, sizeof(out) - inflate_stream.avail_out); if (result.size() < inflate_stream.total_out) { result.append(out, inflate_stream.total_out - result.size()); } } while (code == Z_OK); inflateEnd(&inflate_stream); if (code != Z_STREAM_END) { throw std::runtime_error(inflate_stream.msg ? inflate_stream.msg : "decompression error"); } return result; } // gzip压缩 std::string compress(const std::string &raw) { z_stream deflate_stream; memset(&deflate_stream, 0, sizeof(deflate_stream)); // TODO: reuse z_streams if (deflateInit2(&deflate_stream, Z_DEFAULT_COMPRESSION) != Z_OK) { throw std::runtime_error("failed to initialize deflate"); } deflate_stream.next_in = reinterpret_cast<Bytef *>(const_cast<char *>(raw.data())); deflate_stream.avail_in = uInt(raw.size()); std::string result; char out[16384]; int code; do { deflate_stream.next_out = reinterpret_cast<Bytef *>(out); deflate_stream.avail_out = sizeof(out); code = deflate(&deflate_stream, Z_FINISH); if (result.size() < deflate_stream.total_out) { // append the block to the output string result.append(out, deflate_stream.total_out - result.size()); } } while (code == Z_OK); deflateEnd(&deflate_stream); if (code != Z_STREAM_END) { throw std::runtime_error(deflate_stream.msg); } return result; }