How does zip::write::SimpleFileOptions control compression method and level for archive entries?

zip::write::SimpleFileOptions configures how individual files are compressed when added to a ZIP archive, specifying the compression method (stored, deflated, bzip2, zstd, etc.) and compression level. Each file in a ZIP archive can have different compression settings—text files might use high compression, already-compressed files might use no compression, and large files might balance compression speed versus size reduction. The options are set on a per-file basis through the FileOptions trait, allowing fine-grained control over archive contents.

Basic File Options

use zip::write::SimpleFileOptions;
use zip::CompressionMethod;
use std::io::Write;
 
fn basic_options() -> zip::result::ZipResult<()> {
    let file = std::fs::File::create("archive.zip")?;
    let mut zip = zip::ZipWriter::new(file);
    
    // Default options: stored (no compression)
    let options = SimpleFileOptions::default();
    
    zip.start_file("readme.txt", options)?;
    zip.write_all(b"Hello, World!")?;
    
    zip.finish()?;
    Ok(())
}

Default SimpleFileOptions uses no compression (stored method).

Compression Method Selection

use zip::write::SimpleFileOptions;
use zip::CompressionMethod;
use std::io::Write;
 
fn compression_methods() -> zip::result::ZipResult<()> {
    let file = std::fs::File::create("archive.zip")?;
    let mut zip = zip::ZipWriter::new(file);
    
    // Stored: no compression
    let stored = SimpleFileOptions::default()
        .compression_method(CompressionMethod::Stored);
    
    // Deflated: standard ZIP compression
    let deflated = SimpleFileOptions::default()
        .compression_method(CompressionMethod::Deflated);
    
    // Bzip2: better compression, slower
    let bzip2 = SimpleFileOptions::default()
        .compression_method(CompressionMethod::Bzip2);
    
    // Zstd: modern compression algorithm
    let zstd = SimpleFileOptions::default()
        .compression_method(CompressionMethod::Zstd);
    
    zip.start_file("stored.bin", stored)?;
    zip.write_all(b"uncompressed data")?;
    
    zip.start_file("deflated.txt", deflated)?;
    zip.write_all(b"compressed text data")?;
    
    zip.finish()?;
    Ok(())
}

compression_method() specifies how file contents are compressed.

Compression Level

use zip::write::SimpleFileOptions;
use zip::CompressionMethod;
use std::io::Write;
 
fn compression_levels() -> zip::result::ZipResult<()> {
    let file = std::fs::File::create("archive.zip")?;
    let mut zip = zip::ZipWriter::new(file);
    
    // Compression level: 0 (fastest) to 9 (best compression)
    let fast = SimpleFileOptions::default()
        .compression_method(CompressionMethod::Deflated)
        .compression_level(Some(1)); // Fast compression
    
    let balanced = SimpleFileOptions::default()
        .compression_method(CompressionMethod::Deflated)
        .compression_level(Some(6)); // Default level
    
    let best = SimpleFileOptions::default()
        .compression_method(CompressionMethod::Deflated)
        .compression_level(Some(9)); // Best compression
    
    zip.start_file("fast.txt", fast)?;
    zip.write_all(b"Data compressed quickly")?;
    
    zip.start_file("balanced.txt", balanced)?;
    zip.write_all(b"Data with balanced compression")?;
    
    zip.start_file("best.txt", best)?;
    zip.write_all(b"Data with maximum compression")?;
    
    zip.finish()?;
    Ok(())
}

compression_level() controls the trade-off between speed and compression ratio.

Combining Compression Method and Level

use zip::write::SimpleFileOptions;
use zip::CompressionMethod;
use std::io::Write;
 
fn combined_options() -> zip::result::ZipResult<()> {
    let file = std::fs::File::create("archive.zip")?;
    let mut zip = zip::ZipWriter::new(file);
    
    // Method and level combined
    let options = SimpleFileOptions::default()
        .compression_method(CompressionMethod::Deflated)
        .compression_level(Some(9));
    
    zip.start_file("highly_compressed.txt", options)?;
    zip.write_all(b"Very compressible text data...")?;
    
    zip.finish()?;
    Ok(())
}

Method and level work together to control compression behavior.

Stored for Pre-compressed Files

use zip::write::SimpleFileOptions;
use zip::CompressionMethod;
use std::io::Write;
 
fn store_precompressed() -> zip::result::ZipResult<()> {
    let file = std::fs::File::create("archive.zip")?;
    let mut zip = zip::ZipWriter::new(file);
    
    // Already compressed files shouldn't be recompressed
    let store_only = SimpleFileOptions::default()
        .compression_method(CompressionMethod::Stored);
    
    // Adding a JPEG (already compressed)
    let jpeg_data = include_bytes!("image.jpg");
    zip.start_file("image.jpg", store_only)?;
    zip.write_all(jpeg_data)?;
    
    // Adding a ZIP file (already compressed)
    let zip_data = include_bytes!("data.zip");
    zip.start_file("data.zip", store_only)?;
    zip.write_all(zip_data)?;
    
    zip.finish()?;
    Ok(())
}

Stored method avoids redundant compression on already-compressed files.

Per-File Compression Strategy

use zip::write::SimpleFileOptions;
use zip::CompressionMethod;
use std::io::Write;
use std::path::Path;
 
fn per_file_compression() -> zip::result::ZipResult<()> {
    let file = std::fs::File::create("archive.zip")?;
    let mut zip = zip::ZipWriter::new(file);
    
    // Function to choose compression based on extension
    fn get_options(path: &Path) -> SimpleFileOptions {
        let extension = path.extension()
            .and_then(|e| e.to_str())
            .unwrap_or("");
        
        match extension {
            // Already compressed: store without compression
            "zip" | "gz" | "bz2" | "zst" | "jpg" | "png" | "mp3" | "mp4" => {
                SimpleFileOptions::default()
                    .compression_method(CompressionMethod::Stored)
            }
            // Highly compressible: maximum compression
            "txt" | "json" | "xml" | "csv" | "html" | "css" | "js" => {
                SimpleFileOptions::default()
                    .compression_method(CompressionMethod::Deflated)
                    .compression_level(Some(9))
            }
            // Binary files: balanced compression
            "exe" | "dll" | "so" | "bin" => {
                SimpleFileOptions::default()
                    .compression_method(CompressionMethod::Deflated)
                    .compression_level(Some(6))
            }
            // Default: standard compression
            _ => {
                SimpleFileOptions::default()
                    .compression_method(CompressionMethod::Deflated)
            }
        }
    }
    
    // Add different file types with appropriate compression
    let files = vec!["readme.txt", "data.json", "image.jpg", "program.exe"];
    
    for filename in files {
        let options = get_options(Path::new(filename));
        zip.start_file(filename, options)?;
        // Write file contents...
    }
    
    zip.finish()?;
    Ok(())
}

Different file types benefit from different compression strategies.

Large File Options

use zip::write::SimpleFileOptions;
use zip::CompressionMethod;
use std::io::{Write, Read};
 
fn large_file_compression() -> zip::result::ZipResult<()> {
    let file = std::fs::File::create("large_archive.zip")?;
    let mut zip = zip::ZipWriter::new(file);
    
    // For large files: faster compression to reduce CPU time
    let large_file_options = SimpleFileOptions::default()
        .compression_method(CompressionMethod::Deflated)
        .compression_level(Some(3)) // Faster compression
        .large_file(true); // Enable ZIP64 for large files
    
    zip.start_file("large_data.bin", large_file_options)?;
    
    // Stream large file contents
    let mut large_file = std::fs::File::open("large_data.bin")?;
    let mut buffer = [0u8; 8192];
    loop {
        let bytes_read = large_file.read(&mut buffer)?;
        if bytes_read == 0 {
            break;
        }
        zip.write_all(&buffer[..bytes_read])?;
    }
    
    zip.finish()?;
    Ok(())
}

Large files may benefit from faster compression levels to reduce processing time.

ZIP64 Support for Large Archives

use zip::write::SimpleFileOptions;
use zip::CompressionMethod;
 
fn zip64_options() -> SimpleFileOptions {
    SimpleFileOptions::default()
        .compression_method(CompressionMethod::Deflated)
        .compression_level(Some(6))
        .large_file(true) // ZIP64 for files > 4GB
}
 
fn large_archive_support() {
    // ZIP64 extensions support:
    // - Files larger than 4GB
    // - Archives with more than 65535 files
    // - Archives larger than 4GB
    
    let options = zip64_options();
    
    // These require ZIP64:
    // - File size > 4,294,967,295 bytes
    // - More than 65,535 files in archive
    // - Archive size > 4GB
}

large_file(true) enables ZIP64 extensions for files exceeding standard ZIP limits.

Compression Method Comparison

use zip::write::SimpleFileOptions;
use zip::CompressionMethod;
use std::io::Write;
 
fn method_comparison() -> zip::result::ZipResult<()> {
    let file = std::fs::File::create("comparison.zip")?;
    let mut zip = zip::ZipWriter::new(file);
    
    let data = b"Repetitive text data that compresses well. ".repeat(100);
    
    // Stored: no compression (fastest, largest)
    zip.start_file("stored.txt", SimpleFileOptions::default()
        .compression_method(CompressionMethod::Stored))?;
    zip.write_all(&data)?;
    
    // Deflated: standard compression (balanced)
    zip.start_file("deflated.txt", SimpleFileOptions::default()
        .compression_method(CompressionMethod::Deflated))?;
    zip.write_all(&data)?;
    
    // Bzip2: better compression (slower)
    zip.start_file("bzip2.txt", SimpleFileOptions::default()
        .compression_method(CompressionMethod::Bzip2))?;
    zip.write_all(&data)?;
    
    // Zstd: modern compression (fast + good compression)
    zip.start_file("zstd.txt", SimpleFileOptions::default()
        .compression_method(CompressionMethod::Zstd))?;
    zip.write_all(&data)?;
    
    zip.finish()?;
    Ok(())
}

Different methods offer trade-offs between speed and compression ratio.

Time-Based Compression Choice

use zip::write::SimpleFileOptions;
use zip::CompressionMethod;
use std::time::Instant;
use std::io::Write;
 
fn time_compression() -> zip::result::ZipResult<()> {
    let data = b"Test data for compression timing. ".repeat(10000);
    
    // Measure different compression levels
    for level in [1, 3, 6, 9] {
        let start = Instant::now();
        
        let file = std::fs::File::create(format!("level_{}.zip", level))?;
        let mut zip = zip::ZipWriter::new(file);
        
        let options = SimpleFileOptions::default()
            .compression_method(CompressionMethod::Deflated)
            .compression_level(Some(level));
        
        zip.start_file("data.txt", options)?;
        zip.write_all(&data)?;
        zip.finish()?;
        
        println!("Level {}: {:?}", level, start.elapsed());
    }
    
    Ok(())
}

Compression level affects CPU time and archive size.

Archive Metadata Options

use zip::write::SimpleFileOptions;
use zip::CompressionMethod;
use std::io::Write;
 
fn metadata_options() -> zip::result::ZipResult<()> {
    let file = std::fs::File::create("archive.zip")?;
    let mut zip = zip::ZipWriter::new(file);
    
    let options = SimpleFileOptions::default()
        .compression_method(CompressionMethod::Deflated)
        .compression_level(Some(6))
        .unix_permissions(0o644) // File permissions
        .last_modified_time(
            zip::DateTime::from_date_and_time(2024, 1, 15, 12, 0, 0)?
        );
    
    zip.start_file("document.txt", options)?;
    zip.write_all(b"File with metadata")?;
    
    zip.finish()?;
    Ok(())
}

SimpleFileOptions also controls file permissions and timestamps.

Compression Level Trade-offs

use zip::write::SimpleFileOptions;
use zip::CompressionMethod;
 
fn level_tradeoffs() {
    // Level 0: No compression (stored)
    // - Fastest write
    // - Largest archive
    // - Use for: already compressed files
    
    // Level 1-3: Fast compression
    // - Quick compression
    // - Moderate size reduction
    // - Use for: large files, limited CPU
    
    // Level 4-6: Balanced
    // - Default level
    // - Good balance of speed and size
    // - Use for: general purpose
    
    // Level 7-9: Maximum compression
    // - Best compression ratio
    // - Slowest compression
    // - Use for: small files, storage optimization
    
    let fast = SimpleFileOptions::default()
        .compression_method(CompressionMethod::Deflated)
        .compression_level(Some(2));
    
    let balanced = SimpleFileOptions::default()
        .compression_method(CompressionMethod::Deflated)
        .compression_level(Some(6));
    
    let maximum = SimpleFileOptions::default()
        .compression_method(CompressionMethod::Deflated)
        .compression_level(Some(9));
}

Compression levels trade speed for size reduction.

Compression Method Characteristics

use zip::write::SimpleFileOptions;
use zip::CompressionMethod;
 
fn method_characteristics() {
    // Stored (no compression)
    // - Speed: Fastest
    // - Ratio: None (same size)
    // - Compatibility: Universal
    // - Use for: pre-compressed files
    
    // Deflated
    // - Speed: Fast
    // - Ratio: Good
    // - Compatibility: Universal
    // - Use for: general purpose
    
    // Bzip2
    // - Speed: Slow
    // - Ratio: Better than deflate
    // - Compatibility: Requires support
    // - Use for: maximum compression
    
    // Zstd
    // - Speed: Fast (faster than deflate at high levels)
    // - Ratio: Better than deflate
    // - Compatibility: Requires support
    // - Use for: modern applications
    
    let stored = SimpleFileOptions::default()
        .compression_method(CompressionMethod::Stored);
    
    let deflated = SimpleFileOptions::default()
        .compression_method(CompressionMethod::Deflated);
    
    let bzip2 = SimpleFileOptions::default()
        .compression_method(CompressionMethod::Bzip2);
    
    let zstd = SimpleFileOptions::default()
        .compression_method(CompressionMethod::Zstd);
}

Each method has different speed, compression, and compatibility characteristics.

Real-World Example: Backup Archive

use zip::write::SimpleFileOptions;
use zip::CompressionMethod;
use std::io::Write;
use std::path::Path;
use walkdir::WalkDir;
 
fn create_backup_archive(source_dir: &Path, output: &Path) -> zip::result::ZipResult<()> {
    let file = std::fs::File::create(output)?;
    let mut zip = zip::ZipWriter::new(file);
    
    for entry in WalkDir::new(source_dir) {
        let entry = entry?;
        let path = entry.path();
        
        if path.is_file() {
            let relative = path.strip_prefix(source_dir).unwrap();
            
            // Choose compression based on file type
            let options = get_compression_options(path);
            
            zip.start_file(relative.to_string_lossy(), options)?;
            
            let data = std::fs::read(path)?;
            zip.write_all(&data)?;
        }
    }
    
    zip.finish()?;
    Ok(())
}
 
fn get_compression_options(path: &Path) -> SimpleFileOptions {
    let ext = path.extension()
        .and_then(|e| e.to_str())
        .unwrap_or("")
        .to_lowercase();
    
    // Pre-compressed files
    let already_compressed = ["zip", "gz", "bz2", "zst", "xz", "jpg", "png", 
                              "gif", "mp3", "mp4", "pdf", "7z"];
    
    // Text files
    let text_files = ["txt", "json", "xml", "csv", "html", "css", "js", 
                      "md", "log", "yml", "yaml", "toml"];
    
    if already_compressed.contains(&ext.as_str()) {
        SimpleFileOptions::default()
            .compression_method(CompressionMethod::Stored)
    } else if text_files.contains(&ext.as_str()) {
        SimpleFileOptions::default()
            .compression_method(CompressionMethod::Deflated)
            .compression_level(Some(9))
    } else {
        SimpleFileOptions::default()
            .compression_method(CompressionMethod::Deflated)
            .compression_level(Some(6))
    }
}

Backup archives use per-file compression strategies based on content.

Real-World Example: Application Package

use zip::write::SimpleFileOptions;
use zip::CompressionMethod;
use std::io::Write;
 
fn create_app_package() -> zip::result::ZipResult<()> {
    let file = std::fs::File::create("app.zip")?;
    let mut zip = zip::ZipWriter::new(file);
    
    // Executable: moderate compression
    let exe_options = SimpleFileOptions::default()
        .compression_method(CompressionMethod::Deflated)
        .compression_level(Some(6))
        .unix_permissions(0o755);
    
    zip.start_file("bin/application", exe_options)?;
    zip.write_all(&include_bytes!("application")[..])?;
    
    // Configuration: high compression (text files compress well)
    let config_options = SimpleFileOptions::default()
        .compression_method(CompressionMethod::Deflated)
        .compression_level(Some(9));
    
    zip.start_file("config/settings.json", config_options)?;
    zip.write_all(include_str!("settings.json").as_bytes())?;
    
    // Images: no compression (already compressed)
    let image_options = SimpleFileOptions::default()
        .compression_method(CompressionMethod::Stored);
    
    zip.start_file("assets/icon.png", image_options)?;
    zip.write_all(&include_bytes!("icon.png")[..])?;
    
    // Documentation: high compression
    let doc_options = SimpleFileOptions::default()
        .compression_method(CompressionMethod::Deflated)
        .compression_level(Some(9));
    
    zip.start_file("docs/README.md", doc_options)?;
    zip.write_all(include_str!("README.md").as_bytes())?;
    
    zip.finish()?;
    Ok(())
}

Application packages optimize compression per content type.

Real-World Example: Log Archive

use zip::write::SimpleFileOptions;
use zip::CompressionMethod;
use std::io::Write;
 
fn archive_logs(log_dir: &str, output: &str) -> zip::result::ZipResult<()> {
    let file = std::fs::File::create(output)?;
    let mut zip = zip::ZipWriter::new(file);
    
    // Log files compress very well with high compression
    let log_options = SimpleFileOptions::default()
        .compression_method(CompressionMethod::Deflated)
        .compression_level(Some(9));
    
    for entry in std::fs::read_dir(log_dir)? {
        let entry = entry?;
        let path = entry.path();
        
        if path.extension().map(|e| e == "log").unwrap_or(false) {
            let filename = path.file_name().unwrap().to_string_lossy();
            zip.start_file(&filename, log_options)?;
            
            let contents = std::fs::read(&path)?;
            zip.write_all(&contents)?;
        }
    }
    
    zip.finish()?;
    Ok(())
}

Log files benefit from maximum compression due to repetitive content.

Synthesis

Compression method comparison:

Method Speed Compression Compatibility Use Case
Stored Fastest None Universal Pre-compressed files
Deflated Fast Good Universal General purpose
Bzip2 Slow Better Common Maximum compression
Zstd Fast Better Modern Modern applications

Compression level trade-offs:

Level Speed Size Use Case
0 Fastest Largest Already compressed
1-3 Fast Moderate Large files
4-6 Balanced Good General purpose
7-9 Slow Smallest Storage optimization

Per-file strategy:

File Type Recommended Options
Text (.txt, .json, .xml) Deflated level 9
Images (.jpg, .png) Stored
Videos (.mp4, .mkv) Stored
Archives (.zip, .gz) Stored
Binaries (.exe, .dll) Deflated level 6
Source code Deflated level 9

Key insight: zip::write::SimpleFileOptions controls per-file compression through compression_method() and compression_level(), allowing different strategies for different file types. The Stored method avoids redundant compression for already-compressed files, while Deflated with level 9 maximizes compression for text files. Large files benefit from lower compression levels (1-3) to reduce CPU time, while small files can use maximum compression (9) without significant overhead. The large_file(true) option enables ZIP64 for files exceeding 4GB or archives with more than 65,535 files. Per-file compression allows archives to optimize both size and processing time based on content characteristics—compressing highly compressible text heavily while storing pre-compressed binaries without additional overhead.