Библиотека zip для Rust: полное руководство по работе с ZIP-архивами
В современной разработке на Rust работа с архивами — востребованная задача. Будь то упаковка логов, распаковка конфигураций или создание бэкапов — стандартная библиотека zip (crate zip) является де-факто решением для чтения и записи ZIP-файлов. В этой статье мы подробно разберём, как установить библиотеку, создать архив, извлечь файлы, а также рассмотрим продвинутые техники: работу с паролями, потоками и большими данными.
Установка и подключение
Добавьте зависимость в Cargo.toml:
[dependencies]
zip = "2.1"
После этого импортируйте необходимые модули в коде:
use std::fs::File;
use std::io::{Read, Write, BufReader, BufWriter};
use zip::ZipWriter;
use zip::write::FileOptions;
use zip::read::ZipArchive;
Создание ZIP-архива
Для создания нового архива используется ZipWriter. Рассмотрим базовый пример — упакуем два текстовых файла:
use std::fs::File;
use std::io::Write;
use zip::ZipWriter;
use zip::write::FileOptions;
fn create_archive() -> zip::result::ZipResult<()> {
let file = File::create("example.zip")?;
let mut zip = ZipWriter::new(file);
// Добавляем первый файл
zip.start_file("hello.txt", FileOptions::default())?;
zip.write_all(b"Hello, Rust archive!")?;
// Добавляем второй файл с компрессией
let options = FileOptions::default()
.compression_method(zip::CompressionMethod::Deflated)
.unix_permissions(0o755);
zip.start_file("data/config.json", options)?;
zip.write_all(b"{\"version\": 1}")?;
zip.finish()?;
Ok(())
}
Важно: метод start_file открывает новый файл внутри архива. Опции позволяют задать метод сжатия (по умолчанию Stored — без сжатия, Deflated — стандартное сжатие ZIP).
Чтение и извлечение архива
Для чтения используется ZipArchive. Ниже — функция, которая выводит список файлов и извлекает их в текущую директорию:
use std::fs::File;
use std::io::{Read, BufReader};
use zip::ZipArchive;
fn extract_archive() -> zip::result::ZipResult<()> {
let file = File::open("example.zip")?;
let reader = BufReader::new(file);
let mut archive = ZipArchive::new(reader)?;
for i in 0..archive.len() {
let mut entry = archive.by_index(i)?;
let name = entry.name().to_string();
println!("Извлекаем: {}", name);
// Создаём файл на диске
let mut output = File::create(&name)?;
std::io::copy(&mut entry, &mut output)?;
}
Ok(())
}
Метод by_index возвращает итератор по записям. Если нужен доступ по имени — используйте by_name("path/to/file.txt"). Обратите внимание: имена в ZIP могут содержать пути с разделителем / — это нормально для кросс-платформенности.
Работа с паролями (шифрование)
Библиотека zip поддерживает шифрование на основе пароля через алгоритм AES (по умолчанию AES-256). Для создания зашифрованного архива:
use zip::ZipWriter;
use zip::write::FileOptions;
use zip::AesMode;
fn create_encrypted_archive() -> zip::result::ZipResult<()> {
let file = File::create("secret.zip")?;
let mut zip = ZipWriter::new(file);
let options = FileOptions::default()
.compression_method(zip::CompressionMethod::Deflated)
.with_aes_encryption(AesMode::Aes256, "my_strong_password");
zip.start_file("secret.txt", options)?;
zip.write_all(b"Top secret data")?;
zip.finish()?;
Ok(())
}
Для чтения зашифрованного архива передайте пароль в метод by_index_decrypt или by_name_decrypt:
let mut entry = archive.by_name_decrypt("secret.txt", "my_strong_password")?;
let mut content = String::new();
entry.read_to_string(&mut content)?;
println!("Содержимое: {}", content);
Важно: шифрование доступно только в версии zip 2.x и требует включения фичи aes-crypto в Cargo.toml:
zip = { version