العمل مع أرشيفات ZIP في Go (Golang): إنشاء وقراءة واستخراج الملفات

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة

العمل مع أرشيفات ZIP في Go (Golang): دليل شامل



في التطوير الحديث باستخدام Go (Golang)، يعد العمل مع الأرشيفات من المهام الشائعة. سواء كان ذلك لتعبئة السجلات، أو تحميل الملفات إلى الخادم، أو إنشاء نسخ احتياطية - توفر المكتبة القياسية archive/zip كل ما هو ضروري لإنشاء وقراءة وتعديل أرشيفات ZIP دون الحاجة إلى تثبيت تبعيات خارجية. في هذه المقالة، سنستعرض العمليات الأساسية مع ZIP في Go مع أمثلة عملية.



الإمكانيات الأساسية لحزمة archive/zip

حزمة archive/zip مضمنة في المكتبة القياسية لـ Go وتدعم:

  • إنشاء أرشيفات ZIP جديدة بهيكل مجلدات عشوائي
  • قراءة محتويات الأرشيفات الموجودة
  • استخراج ملفات فردية أو الأرشيف بأكمله
  • إضافة ملفات إلى أرشيف موجود (عن طريق النسخ)
  • التعامل مع البيانات الوصفية للملفات (التاريخ، صلاحيات الوصول، التعليقات)
  • المعالجة التدفقية (بدون تحميل الأرشيف بأكمله في الذاكرة)


إنشاء أرشيف ZIP في Go

لإنشاء أرشيف، يُستخدم zip.NewWriter() الذي يستقبل io.Writer. يتيح ذلك كتابة الأرشيف إما إلى ملف أو إلى مخزن مؤقت (مثلاً للإرسال عبر HTTP).



package main

import ( "archive/zip" "bytes" "fmt" "io" "log" "os")

func createZip() { // إنشاء مخزن مؤقت للأرشيف buf := new(bytes.Buffer) writer := zip.NewWriter(buf)

// إضافة ملف بنص file1, err := writer.Create("hello.txt") if err != nil { log.Fatal(err) } _, err = file1.Write([]byte("مرحباً بالعالم! هذا ملف من أرشيف ZIP.")) if err != nil { log.Fatal(err) }

// إضافة ملف في مجلد فرعي file2, err := writer.Create("docs/readme.md") if err != nil { log.Fatal(err) } _, err = file2.Write([]byte("# توثيقمحتوى readme.")) if err != nil { log.Fatal(err) }

// إغلاق الكاتب إلزامي err = writer.Close() if err != nil { log.Fatal(err) }

// حفظ الأرشيف في ملف err = os.WriteFile("example.zip", buf.Bytes(), 0644) if err != nil { log.Fatal(err) } fmt.Println("تم إنشاء الأرشيف: example.zip")}

func main() { createZip()}


قراءة واستخراج الملفات من ZIP

لقراءة الأرشيف، يُستخدم zip.OpenReader() أو zip.NewReader() (للبيانات من الذاكرة). كل ملف يمثله هيكل zip.File.



func readZip() {    reader, err := zip.OpenReader("example.zip")    if err != nil {        log.Fatal(err)    }    defer reader.Close()

for _, f := range reader.File { fmt.Printf("الملف: %s (الحجم: %d بايت)", f.Name, f.UncompressedSize64)

// فتح محتوى الملف rc, err := f.Open() if err != nil { log.Fatal(err) }

// قراءة المحتوى content, err := io.ReadAll(rc) if err != nil { log.Fatal(err) } rc.Close()

fmt.Printf("المحتوى: %s

", content) }}


استخراج جميع الملفات إلى القرص

غالباً ما يكون مطلوباً فك ضغط الأرشيف إلى دليل محدد. من المهم هنا إنشاء المجلدات الفرعية بشكل صحيح.



func extractZip(src, dest string) {    reader, err := zip.OpenReader(src)    if err != nil {        log.Fatal(err)    }    defer reader.Close()

for _, f := range reader.File { // مسار الاستخراج fpath := filepath.Join(dest, f.Name)

// التحقق من أن المسار لا يخرج عن نطاق dest (الأمان) if !strings.HasPrefix(fpath, filepath.Clean(dest)+string(os.PathSeparator)) { log.Fatalf("مسار غير صالح: %s", fpath) }

// إنشاء المجلدات if f.FileInfo

توصيات