Rust ZIP压缩与解压库zip32的使用:高效处理ZIP文件格式的编码与解码

Rust ZIP压缩与解压库zip32的使用:高效处理ZIP文件格式的编码与解码

许可证

可选择以下任一许可证:

  • Apache License, Version 2.0
  • MIT license

贡献

除非您明确声明,否则任何提交的贡献都将按照上述双重许可证授权,不附加任何额外条款或条件。

安装

在项目目录中运行以下Cargo命令:

cargo add zip32

或在Cargo.toml中添加:

zip32 = "0.2.0"

示例代码

以下是一个完整的ZIP压缩与解压示例:

use std::fs::File;
use std::io::{Read, Write};
use zip::write::FileOptions;
use zip::{ZipArchive, ZipWriter};

// 创建ZIP文件示例
fn create_zip() -> std::io::Result<()> {
    // 创建新ZIP文件
    let file = File::create("example.zip")?;
    let mut zip = ZipWriter::new(file);
    
    // 添加文件到ZIP
    let options = FileOptions::default()
        .compression_method(zip::CompressionMethod::Deflated);
    
    zip.start_file("hello.txt", options)?;
    zip.write_all(b"Hello, World!")?;
    
    // 完成ZIP文件
    zip.finish()?;
    Ok(())
}

// 解压ZIP文件示例
fn extract_zip() -> std::io::Result<()> {
    // 打开ZIP文件
    let file = File::open("example.zip")?;
    let mut archive = ZipArchive::new(file)?;
    
    // 遍历ZIP中的文件
    for i in 0..archive.len() {
        let mut file = archive.by_index(i)?;
        let outpath = file.sanitized_name();
        
        // 如果是目录则创建
        if (&*file.name()).ends_with('/') {
            std::fs::create_dir_all(&outpath)?;
        } else {
            // 创建文件并写入内容
            if let Some(p) = outpath.parent() {
                if !p.exists() {
                    std::fs::create_dir_all(p)?;
                }
            }
            let mut outfile = File::create(&outpath)?;
            std::io::copy(&mut file, &mut outfile)?;
        }
    }
    Ok(())
}

fn main() {
    // 创建ZIP文件
    if let Err(e) = create_zip() {
        eprintln!("Failed to create zip: {}", e);
    }
    
    // 解压ZIP文件
    if let Err(e) = extract_zip() {
        eprintln!("Failed to extract zip: {}", e);
    }
}

完整示例代码

以下是一个增强版的ZIP处理示例,包含更多实用功能:

use std::fs::{self, File};
use std::io::{self, Read, Write};
use std::path::Path;
use zip::write::FileOptions;
use zip::{CompressionMethod, ZipArchive, ZipWriter};

// 创建包含多个文件和目录的ZIP文件
fn create_advanced_zip(output_path: &str) -> io::Result<()> {
    // 创建新ZIP文件
    let file = File::create(output_path)?;
    let mut zip = ZipWriter::new(file);

    // 设置压缩选项
    let options = FileOptions::default()
        .compression_method(CompressionMethod::Deflated)
        .unix_permissions(0o755); // 设置Unix文件权限

    // 添加文本文件
    zip.start_file("readme.txt", options)?;
    zip.write_all(b"This is a sample ZIP file created with zip32")?;

    // 添加二进制文件
    let binary_data = vec![0u8, 1, 2, 3, 4, 5];
    zip.start_file("data.bin", options)?;
    zip.write_all(&binary_data)?;

    // 添加目录
    zip.add_directory("docs/", options)?;

    // 完成ZIP文件
    zip.finish()?;
    Ok(())
}

// 解压ZIP文件到指定目录
fn extract_to_directory(zip_path: &str, output_dir: &str) -> io::Result<()> {
    // 确保输出目录存在
    fs::create_dir_all(output_dir)?;

    // 打开ZIP文件
    let file = File::open(zip_path)?;
    let mut archive = ZipArchive::new(file)?;

    // 遍历ZIP中的文件
    for i in 0..archive.len() {
        let mut file = archive.by_index(i)?;
        let outpath = Path::new(output_dir).join(file.sanitized_name());

        // 处理目录
        if file.name().ends_with('/') {
            fs::create_dir_all(&outpath)?;
        } else {
            // 确保父目录存在
            if let Some(parent) = outpath.parent() {
                if !parent.exists() {
                    fs::create_dir_all(parent)?;
                }
            }

            // 写入文件内容
            let mut outfile = File::create(&outpath)?;
            io::copy(&mut file, &mut outfile)?;

            // 在Unix系统上保持文件权限
            #[cfg(unix)]
            {
                use std::os::unix::fs::PermissionsExt;
                if let Some(mode) = file.unix_mode() {
                    fs::set_permissions(&outpath, fs::Permissions::from_mode(mode))?;
                }
            }
        }
    }
    Ok(())
}

fn main() -> io::Result<()> {
    let zip_file = "advanced_example.zip";
    let extract_dir = "extracted_files";

    // 创建高级ZIP文件
    create_advanced_zip(zip_file)?;
    println!("成功创建ZIP文件: {}", zip_file);

    // 解压ZIP文件
    extract_to_directory(zip_file, extract_dir)?;
    println!("成功解压到目录: {}", extract_dir);

    Ok(())
}

1 回复

Rust ZIP压缩与解压库zip32的使用:高效处理ZIP文件格式的编码与解码

zip32是Rust生态中一个高效处理ZIP文件格式的库,提供了ZIP文件的压缩和解压功能。它支持读取、创建和修改ZIP文件,是处理ZIP压缩任务的理想选择。

主要特性

  • 支持读取和写入ZIP文件
  • 支持压缩(Deflate算法)和存储(不压缩)两种方式
  • 支持ZIP64格式(大文件支持)
  • 内存友好的流式处理
  • 跨平台支持

安装

在Cargo.toml中添加依赖:

[dependencies]
zip = "0.6"

基本使用方法

1. 创建ZIP文件

use std::fs::File;
use zip::write::FileOptions;
use zip::ZipWriter;

fn create_zip() -> zip::result::ZipResult<()> {
    // 创建目标ZIP文件
    let file = File::create("example.zip")?;
    let mut zip = ZipWriter::new(file);
    
    // 添加文件选项
    let options = FileOptions::default()
        .compression_method(zip::CompressionMethod::Deflated)
        .unix_permissions(0o755);
    
    // 添加一个文件
    zip.start_file("hello.txt", options)?;
    zip.write_all(b"Hello, World!")?;
    
    // 添加一个目录中的文件
    zip.add_directory("docs/", FileOptions::default())?;
    
    // 完成ZIP文件写入
    zip.finish()?;
    Ok(())
}

2. 解压ZIP文件

use std::fs::File;
use std::io;
use std::path::Path;
use zip::ZipArchive;

fn extract_zip(zip_file: &str, dest: &str) -> zip::result::ZipResult<()> {
    let file = File::open(zip_file)?;
    let mut archive = ZipArchive::new(file)?;
    
    for i in 0..archive.len() {
        let mut file = archive.by_index(i)?;
        let outpath = Path::new(dest).join(file.name());
        
        if file.name().ends_with('/') {
            // 创建目录
            std::fs::create_dir_all(&outpath)?;
        } else {
            // 创建文件
            if let Some(p) = outpath.parent() {
                if !p.exists() {
                    std::fs::create_dir_all(p)?;
                }
            }
            let mut outfile = File::create(&outpath)?;
            io::copy(&mut file, &mut outfile)?;
        }
    }
    Ok(())
}

3. 读取ZIP文件内容

use std::fs::File;
use zip::ZipArchive;

fn list_zip_contents(zip_file: &str) -> zip::result::ZipResult<()> {
    let file = File::open(zip_file)?;
    let archive = ZipArchive::new(file)?;
    
    println!("Filename\t\tSize\tCompressed\tRatio");
    for i极速 0..archive.len() {
        let file = archive.by_index(i)?;
        let ratio = (file.compressed_size() as f64 / file.size() as f64) * 100.0;
        println!("{}\t\t{}\t{}\t\t{:.2}%", 
            file.name(), 
            file.size(), 
            file.compressed_size(), 
            ratio);
    }
    Ok(())
}

高级用法

1. 处理密码保护的ZIP文件

use zip::ZipArchive;
use std::fs::File;

fn read_protected_zip(zip_file: &str, password: &str) -> zip::result::ZipResult<()> {
    let file = File::open(zip_file)?;
    let mut archive = ZipArchive::new(file)?;
    
    for i in 0..archive.len() {
        let mut file = archive.by_index_decrypt(i, password.as_bytes())??;
        let mut contents = String::new();
        file.read_to_string(&mut contents)?;
        println!("File {} contents: {}", file.name(), contents);
    }
    Ok(())
}

2. 流式处理大文件

use std::fs::File;
use std::io::{Read, Write};
use zip::write::FileOptions;
use zip::ZipWriter;

fn stream_large_file_to_zip() -> zip::result::ZipResult<()> {
    let file = File::create("large_files.zip")?;
    let mut zip = ZipWriter::new(file);
    
    let options = FileOptions::default()
        .compression_method(zip::CompressionMethod::Deflated);
    
    zip.start_file("large_data.bin", options)?;
    
    // 模拟流式写入大数据
    let chunk_size = 1024 * 1024; // 1MB chunks
    let mut buffer = vec![0; chunk_size];
    let mut source = File::open("large_source.bin")?;
    
    loop {
        let bytes_read = source.read(&mut buffer)?;
        if bytes_read == 0 {
            break;
        }
        zip.write_all(&buffer[..bytes_read])?;
    }
    
    zip.finish()?;
    Ok(())
}

完整示例

以下是一个完整的Rust程序,演示了如何使用zip32库进行ZIP文件的创建、解压和内容查看:

use std::fs::File;
use std::io::{self, Read, Write};
use std::path::Path;
use zip::{write::FileOptions, ZipArchive, ZipWriter};
use zip::result::ZipResult;

fn main() -> ZipResult<()> {
    // 1. 创建一个ZIP文件
    create_sample_zip()?;
    println!("成功创建example.zip文件");

    // 2. 列出ZIP文件内容
    println!("\nZIP文件内容:");
    list_zip_contents("example.zip")?;

    // 3. 解压ZIP文件
    extract_zip("example.zip", "extracted")?;
    println!("\n成功解压到extracted目录");

    Ok(())
}

fn create_sample_zip() -> ZipResult<()> {
    let file = File::create("example.zip")?;
    let mut zip = ZipWriter::new(file);
    
    let options = FileOptions::default()
        .compression_method(zip::CompressionMethod::Deflated);
    
    // 添加文本文件
    zip.start_file("hello.txt", options)?;
    zip.write_all(b"Hello, World!")?;
    
    // 添加二进制文件
    zip.start_file("data.bin", options)?;
    zip.write_all(&[0x01, 0x02, 0x03, 0x04])?;
    
    // 添加目录
    zip.add_directory("docs/", FileOptions::default())?;
    
    zip.finish()?;
    Ok(())
}

fn list_zip_contents(zip_file: &str) -> ZipResult<()> {
    let file = File::open(zip_file)?;
    let archive = ZipArchive::new(file)?;
    
    println!("{:<20} {:>10} {:>10} {:>8}", "文件名", "大小", "压缩后", "压缩率");
    
    for i in 0..archive.len() {
        let file = archive.by_index(i)?;
        let ratio = if file.size() > 0 {
            (file.compressed_size() as f64 / file.size() as f64) * 100.0
        } else { 
            0.0 
        };
        println!("{:<20} {:>10} {:>10} {:>7.2}%", 
            file.name(), 
            file.size(), 
            file.compressed_size(), 
            ratio);
    }
    Ok(())
}

fn extract_zip(zip_file: &str, dest: &str) -> ZipResult<()> {
    let file = File::open(zip_file)?;
    let mut archive = ZipArchive::new(file)?;
    
    for i in 0..archive.len() {
        let mut file = archive.by_index(i)?;
        let outpath = Path::new(dest).join(file.name());
        
        if file.name().ends_with('/') {
            std::fs::create_dir_all(&outpath)?;
        } else {
            if let Some(p) = outpath.parent() {
                if !p.exists() {
                    std::fs::create_dir_all(p)?;
                }
            }
            let mut outfile = File::create(&outpath)?;
            io::copy(&mut file, &mut outfile)?;
        }
    }
    Ok(())
}

注意事项

  1. 处理用户提供的ZIP文件时要注意安全性,防止ZIP炸弹攻击
  2. 对于非常大的文件(>4GB),确保启用ZIP64支持
  3. 跨平台使用时注意文件路径的兼容性问题
  4. 密码保护功能使用传统的ZIP加密,安全性有限

zip32库提供了强大而灵活的ZIP文件处理能力,适合各种压缩解压场景。通过合理使用其API,可以高效地处理ZIP文件操作。

回到顶部