Rust高性能压缩库miniz_oxide_c_api的使用,提供跨平台DEFLATE压缩算法的轻量级Rust实现
Rust高性能压缩库miniz_oxide_c_api的使用,提供跨平台DEFLATE压缩算法的轻量级Rust实现
miniz_oxide是一个纯Rust实现的miniz DEFLATE/zlib编码器/解码器替代品,不使用任何unsafe代码。它可以在no_std环境下构建,但需要使用alloc和collections crate。
主要特性
- 纯Rust实现,不使用unsafe代码
- 支持no_std环境
- 提供C API接口
- 轻量级DEFLATE压缩算法实现
- MIT许可证
版本要求
miniz_oxide 0.8.x需要至少Rust 1.56.0版本 miniz_oxide 0.7.x需要至少Rust 1.50.0版本
示例代码
use miniz_oxide::deflate::compress_to_vec;
use miniz_oxide::inflate::decompress_to_vec;
fn main() {
// 原始数据
let data = b"Hello, this is some test data to compress";
// 压缩数据
let compressed = compress_to_vec(data, 6);
println!("Compressed size: {}", compressed.len());
// 解压数据
let decompressed = decompress_to_vec(&compressed).unwrap();
assert_eq!(data, decompressed.as_slice());
println!("Decompressed matches original!");
}
C API使用示例
miniz_oxide_c_api提供了C语言接口,可以用于C/C++项目中:
#include "miniz.h" // 使用miniz_oxide_c_api提供的头文件
int main() {
// 初始化压缩器
tdefl_compressor *compressor = tdefl_compressor_alloc();
const char *input = "Test data to compress";
size_t input_size = strlen(input);
// 预估最大输出大小
size_t max_output_size = tdefl_compress_bound(input_size);
void *output = malloc(max_output_size);
// 压缩数据
size_t compressed_size = max_output_size;
tdefl_status status = tdefl_compress(compressor, input, &input_size,
output, &compressed_size,
TDEFL_WRITE_ZLIB_HEADER | TDEFL_DEFAULT_MAX_PROBES);
if (status == TDEFL_STATUS_DONE) {
printf("Compressed from %zu to %zu bytes\n", input_size, compressed_size);
}
// 释放资源
free(output);
tdefl_compressor_free(compressor);
return 0;
}
构建和测试
# 运行测试
$ cargo test
# 运行基准测试
$ cargo bench --features=benching
在C/C++项目中使用
链接由build.sh生成的libminiz_oxide_c_api.a静态库,并使用miniz_oxide_c_api提供的miniz.h头文件。
许可证
该库(不包括用于测试的miniz C代码)采用MIT许可证。基于miniz C库的部分采用MIT许可证和非许可证双重许可。
完整示例demo
Rust完整示例
use miniz_oxide::deflate::{compress_to_vec, CompressionLevel};
use miniz_oxide::inflate::decompress_to_vec;
fn main() {
// 原始数据
let data = b"This is a longer text to demonstrate compression and decompression with miniz_oxide in Rust. It contains more data to show the compression ratio and performance.";
// 压缩数据 - 使用默认压缩级别6
let compressed_default = compress_to_vec(data, 6);
println!("Default compression (level 6): {} -> {} bytes", data.len(), compressed_default.len());
// 压缩数据 - 使用最快压缩级别1
let compressed_fast = compress_to_vec(data, 1);
println!("Fast compression (level 1): {} -> {} bytes", data.len(), compressed_fast.len());
// 压缩数据 - 使用最佳压缩级别9
let compressed_best = compress_to_vec(data, 9);
println!("Best compression (level 9): {} -> {} bytes", data.len(), compressed_best.len());
// 解压数据
let decompressed = decompress_to_vec(&compressed_best).unwrap();
assert_eq!(data, decompressed.as_slice());
println!("Decompressed successfully, matches original data!");
// 打印压缩比
println!("Compression ratio (best): {:.2}%",
(compressed_best.len() as f32 / data.len() as f32) * 100.0);
}
C语言完整示例
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "miniz.h" // miniz_oxide_c_api提供的头文件
int main() {
// 初始化压缩器
tdefl_compressor *compressor = tdefl_compressor_alloc();
if (!compressor) {
fprintf(stderr, "Failed to allocate compressor\n");
return 1;
}
const char *input = "This is a sample text to demonstrate miniz_oxide C API compression and decompression functionality.";
size_t input_size = strlen(input);
// 预估最大输出大小并分配内存
size_t max_output_size = tdefl_compress_bound(input_size);
void *compressed_output = malloc(max_output_size);
if (!compressed_output) {
fprintf(stderr, "Memory allocation failed\n");
tdefl_compressor_free(compressor);
return 1;
}
// 压缩数据
size_t compressed_size = max_output_size;
tdefl_status status = tdefl_compress(
compressor,
input,
&input_size,
compressed_output,
&compressed_size,
TDEFL_WRITE_ZLIB_HEADER | TDEFL_DEFAULT_MAX_PROBES
);
if (status != TDEFL_STATUS_DONE) {
fprintf(stderr, "Compression failed with status: %d\n", status);
free(compressed_output);
tdefl_compressor_free(compressor);
return 1;
}
printf("Original size: %zu, Compressed size: %zu\n", input_size, compressed_size);
// 初始化解压器
tinfl_decompressor *decompressor = tinfl_decompressor_alloc();
if (!decompressor) {
fprintf(stderr, "Failed to allocate decompressor\n");
free(compressed_output);
tdefl_compressor_free(compressor);
return 1;
}
// 预估解压后大小并分配内存
size_t decompressed_size = input_size; // 我们知道原始大小
void *decompressed_output = malloc(decompressed_size);
if (!decompressed_output) {
fprintf(stderr, "Memory allocation failed\n");
free(compressed_output);
tdefl_compressor_free(compressor);
tinfl_decompressor_free(decompressor);
return 1;
}
// 解压数据
size_t in_bytes = compressed_size;
size_t out_bytes = decompressed_size;
tinfl_status decomp_status = tinfl_decompress(
decompressor,
compressed_output,
&in_bytes,
decompressed_output,
&out_bytes,
TINFL_FLAG_PARSE_ZLIB_HEADER
);
if (decomp_status != TINFL_STATUS_DONE) {
fprintf(stderr, "Decompression failed with status: %d\n", decomp_status);
} else {
printf("Decompressed successfully. Original and decompressed data match: %s\n",
memcmp(input, decompressed_output, input_size) == 0 ? "true" : "false");
}
// 释放所有资源
free(compressed_output);
free(decompressed_output);
tdefl_compressor_free(compressor);
tinfl_decompressor_free(decompressor);
return 0;
}
1 回复
Rust高性能压缩库miniz_oxide_c_api使用指南
miniz_oxide_c_api是一个提供跨平台DEFLATE压缩算法的轻量级Rust实现库,它是miniz_oxide的C API封装版本。
特性
- 纯Rust实现,无unsafe代码
- 支持DEFLATE压缩/解压缩算法
- 轻量级,无额外依赖
- 提供C API接口,方便与其他语言交互
- 性能接近zlib
安装
在Cargo.toml中添加依赖:
[dependencies]
miniz_oxide_c_api = "0.1"
基本使用示例
压缩数据
use miniz_oxide_c_api::compress;
fn main() {
let input_data = b"This is some test data to compress";
// 压缩级别范围0-10,6是默认值
let compressed_data = compress::compress_to_vec(input_data, 6).unwrap();
println!("Compressed size: {} bytes", compressed_data.len());
}
解压数据
use miniz_oxide_c_api::decompress;
fn main() {
let compressed_data = /* 从某处获取压缩数据 */;
let decompressed_data = decompress::decompress_to_vec(&compressed_data).unwrap();
println!("Decompressed data: {:?}", String::from_utf8_lossy(&decompressed_data));
}
流式压缩/解压缩
对于大文件处理,可以使用流式API:
流式压缩
use miniz_oxide_c_api::stream::{compress, Action, Status, Flush};
fn stream_compress(input: &[u8]) -> Vec<u8> {
let mut compressor = compress::Stream::new();
let mut output = Vec::new();
let mut input_pos = 0;
loop {
let (status, bytes_read, bytes_written) = compressor.compress(
&input[input_pos..],
&mut output,
Flush::Finish
);
input_pos += bytes_read;
if status == Status::StreamEnd {
break;
}
}
output
}
流式解压
use miniz_oxide_c_api::stream::{decompress, Status, Flush};
fn stream_decompress(input: &[u8]) -> Vec<u8> {
let mut decompressor = decompress::Stream::new();
let mut output = Vec::new();
let mut input_pos = 0;
loop {
let (status, bytes_read, bytes_written) = decompressor.decompress(
&input[input_pos..],
&mut output,
Flush::Finish
);
input_pos += bytes_read;
if status == Status::StreamEnd {
break;
}
}
output
}
完整示例demo
下面是一个完整的压缩和解压示例:
use miniz_oxide_c_api::{compress, decompress};
fn main() {
// 原始数据
let original_data = b"This is a test string that will be compressed and then decompressed";
println!("Original data size: {} bytes", original_data.len());
// 压缩数据
let compressed_data = compress::compress_to_vec(original_data, 6).unwrap();
println!("Compressed size: {} bytes", compressed_data.len());
// 解压数据
let decompressed_data = decompress::decompress_to_vec(&compressed_data).unwrap();
println!("Decompressed size: {} bytes", decompressed_data.len());
// 验证数据是否一致
assert_eq!(original_data, decompressed_data.as_slice());
println!("Decompressed data matches original!");
}
性能提示
- 对于小数据块,一次性压缩(
compress_to_vec
)通常比流式API更快 - 压缩级别越高(接近10),压缩率越高但速度越慢
- 解压速度通常不受压缩级别影响
跨语言使用(C API)
miniz_oxide_c_api提供了C兼容的API,可以在其他语言中使用:
#include <stddef.h>
#include <stdint.h>
// 压缩函数
size_t miniz_compress(uint8_t *dest, size_t *dest_len,
const uint8_t *source, size_t source_len,
int level);
// 解压函数
size_t miniz_decompress(uint8_t *dest, size_t *dest_len,
const uint8_t *source, size_t source_len);
注意事项
- 确保解压时提供足够大的输出缓冲区
- 检查所有操作的返回状态
- 对于生产环境,考虑添加错误处理和边界检查
这个库非常适合需要轻量级DEFLATE压缩/解压且希望避免zlib依赖的项目。