Skip to content

Day 82: std.zlib模块:Zlib压缩格式

Zlib是一种数据格式规范,它本身使用Deflate算法进行压缩。与原始的Deflate流相比,Zlib格式在数据前后添加了一个小的头部和尾部(Adler-32校验和)。这使得Zlib成为一个自包含、可验证的压缩数据流,并被广泛应用于各种场景,例如PNG图像文件的像素数据压缩、HTTP压缩以及无数的库和应用程序中。

Zig的std.zlib模块提供了与std.compression.deflate和std.compression.gzip类似的流式API,用于处理Zlib格式的数据。

std.zlib的核心是Stream结构体,它既可以用于压缩也可以用于解压缩。

  • zlib.compressStream(writer, options): 创建一个Zlib压缩流。
  • zlib.decompressStream(reader, options): 创建一个Zlib解压缩流。

这些函数返回一个Stream实例,你可以从它的reader读取解压后的数据,或者向它的writer写入待压缩的数据。

对于较小的数据块,std.zlib也提供了一次性完成操作的便捷函数。

  • zlib.compress(allocator, input, options): 将整个input切片压缩,并返回一个新的、在堆上分配的包含压缩数据的切片。
  • zlib.decompress(allocator, input, options, max_size): 解压缩整个input切片。
const std = @import("std");
const zlib = std.zlib;
pub fn main() !void {
const allocator = std.testing.allocator;
const original_data = "zlib is a widely used compression library.";
// 压缩
const compressed_data = try zlib.compress(allocator, original_data, .{});
defer allocator.free(compressed_data);
std.debug.print("Original size: {d}, Compressed size: {d}\n", .{
original_data.len,
compressed_data.len,
});
// 解压缩
const decompressed_data = try zlib.decompress(allocator, compressed_data, .{}, 1024);
defer allocator.free(decompressed_data);
std.debug.print("Decompressed data is same as original: {}\n", .{
std.mem.eql(u8, original_data, decompressed_data),
});
}

PNG图像格式使用Zlib来压缩其像素数据。一个PNG文件由多个“块”(chunks)组成,其中IDAT块就包含了Zlib压缩的图像数据。虽然完整的PNG解析很复杂,但我们可以模拟解压一个IDAT块的过程。

// 假设 idat_chunk_data 是从PNG文件中读取的原始IDAT块内容
const idat_chunk_data: []const u8 = ...;
// 解压像素数据
const pixel_data = try zlib.decompress(allocator, idat_chunk_data, .{}, max_pixel_buffer_size);
// 现在 pixel_data 中包含了可以用于渲染的原始像素信息

创建一个函数,它接收一个Reader(代表一个Zlib压缩的数据源)和一个Writer。使用zlib.decompressStream和std.io.copy,将解压后的数据从源Reader泵送到目标Writer。

  • 窗口大小(Window Bits) Zlib(以及Deflate)使用一个滑动窗口来查找重复的数据序列。窗口的大小会影响压缩率和内存使用。std.zlib的Options结构体允许你配置这个参数。

  • Flush(刷新) 在流式压缩中,有时你需要确保到目前为止的所有数据都已被完全写入下游的Writer,即使这意味着牺牲一些压缩率。compressStream的writer提供了flush()方法来执行此操作。这在网络协议中很有用。

  • Adler-32校验和 Adler-32是Zlib用于验证数据完整性的校验和算法。它比CRC-32计算更快,但可靠性稍低。std.zlib模块会自动处理Adler-32的计算和验证。

std.zlib为Zig提供了对一个基础且广泛使用的压缩格式的强大、原生的支持。它的API与标准库中的其他压缩模块保持一致,使得在不同算法之间切换变得相对容易。

除了Deflate, Gzip和Zlib,还有许多其他的压缩算法。虽然它们可能没有被包含在Zig的标准库中,但Zig强大的C FFI能力使得集成像bzip2, lzma等外部压缩库变得非常简单。这让Zig开发者可以根据具体需求,在内置的便利性和第三方库的广泛功能之间做出选择。