العمل مع أرشيفات ZIP في Rust باستخدام مكتبة zip
عند التطوير بلغة Rust، غالبًا ما تنشأ الحاجة إلى ضغط الملفات في أرشيفات ZIP أو استخراج البيانات منها. قد يكون ذلك ضروريًا لتوزيع البرامج، إنشاء النسخ الاحتياطية، معالجة الأرشيفات التي رفعها المستخدمون، أو تجميع الحزم. لا تتضمن المكتبة القياسية لـ Rust أدوات مدمجة للعمل مع ZIP، لكن النظام البيئي يقدم مكتبة قوية وسهلة الاستخدام zip.
في هذه المقالة، سنشرح بالتفصيل كيفية استخدام مكتبة zip لإنشاء وقراءة واستخراج أرشيفات ZIP. ستتعلم كيفية تثبيت المكتبة، العمل مع الملفات والمجلدات، معالجة الأخطاء، وإدارة الضغط.
تثبيت مكتبة zip
للبدء، أضف التبعية إلى ملف Cargo.toml الخاص بمشروعك:
[dependencies]zip = "2.2"المكتبة مدعومة بنشاط وتستخدم الإمكانيات الحديثة لـ Rust. بعد إضافة التبعية، يمكنك استيرادها في الكود:
use zip::ZipWriter;use zip::read::ZipArchive;use std::io::{Read, Write, BufWriter, BufReader};use std::fs::{self, File};إنشاء أرشيف ZIP
يتكون إنشاء الأرشيف من عدة خطوات: فتح ملف للكتابة، تهيئة ZipWriter، إضافة الملفات، وإنهاء الكتابة. لنلق نظرة على مثال يقوم بضغط ملف نصي واحد:
use std::fs::File;use zip::ZipWriter;use zip::write::FileOptions;use std::io::Write;
fn create_archive() -> zip::result::ZipResult<()> { 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, Rust ZIP!")?;
zip.finish()?; Ok(())}هنا نقوم بـ:
- إنشاء ملف
example.zipفي المجلد الحالي. - تهيئة
ZipWriter. - تكوين معلمات الملف: طريقة الضغط
Deflated(الضغط القياسي) وصلاحيات الوصول. - إضافة ملف
hello.txtوكتابة المحتوى فيه. - إنهاء الكتابة باستدعاء
finish().
لإضافة عدة ملفات أو مجلد كامل، استخدم حلقة على الملفات في المجلد:
fn add_directory(zip: &mut ZipWriter<File>, dir_path: &str) -> zip::result::ZipResult<()> { for entry in walkdir::WalkDir::new(dir_path) { let entry = entry?; let path = entry.path(); if path.is_file() { let name = path.strip_prefix(dir_path).unwrap().to_str().unwrap(); zip.start_file(name, FileOptions::default())?; let mut f = File::open(path)?; std::io::copy(&mut f, zip)?; } } Ok(())}لاحظ: للتنقل التكراري عبر المجلدات، من المناسب استخدام crate walkdir، لكن يجب إضافته بشكل منفصل.
قراءة واستخراج أرشيف ZIP
لقراءة الأرشيف، يُستخدم ZipArchive. فيما يلي مثال يعرض قائمة الملفات في الأرشيف ويستخرجها إلى مجلد محدد:
use zip::ZipArchive;use std::io::Read;
fn extract_archive(archive_path: &str, output_dir: &str) -> zip::result::ZipResult<()> { let file = File::open(archive_path)?; let mut archive = ZipArchive::new(file)?;
for i in 0..archive.len() { let mut entry = archive.by_index(i)?; let entry_name = entry.name().to_string(); println!("يتم استخراج: {}", entry_name);
// إنشاء المسار الكامل للملف let output_path = format!("{}/{}", output_dir, entry_nam