مثال حول ملف مجلد ضغط Java

اليوم سنتناول مثالاً على ملف ضغط Java zip. سنقوم أيضاً بضغط مجلد وإنشاء ملف zip باستخدام برنامج Java.

Java ZIP

java.util.zip.ZipOutputStream يمكن استخدامه لضغط ملف إلى تنسيق ZIP. نظرًا لأن ملف zip يمكن أن يحتوي على عدة إدخالات ، يستخدم ZipOutputStream java.util.zip.ZipEntry لتمثيل إدخال ملف zip.

ملف ZIP Java

إنشاء أرشيف zip لملف واحد يكون أمرًا سهلاً جداً ، نحتاج إلى إنشاء كائن ZipOutputStream من كائن FileOutputStream لملف الوجهة. ثم نضيف ZipEntry جديدة إلى ZipOutputStream ونستخدم FileInputStream لقراءة ملف المصدر إلى كائن ZipOutputStream. بمجرد الانتهاء من الكتابة ، نحتاج إلى إغلاق ZipEntry وتحرير جميع الموارد.

مجلد ضغط Java

تضغط مجلد أمر صعب قليلاً، أولاً نحتاج إلى الحصول على قائمة الملفات كمسارات مطلقة. ثم نعالج كل منها بشكل منفصل. نحتاج إلى إضافة `ZipEntry` لكل ملف واستخدام `FileInputStream` لقراءة محتوى الملف الأصلي وتخزينه في `ZipEntry` المقابل لتلك الملف.

مثال على الضغط في جافا

فيما يلي برنامج جافا يظهر كيفية ضغط ملف واحد أو مجلد في جافا.

package com.journaldev.files;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

public class ZipFiles {
    
    List filesListInDir = new ArrayList();

    public static void main(String[] args) {
        File file = new File("/Users/pankaj/sitemap.xml");
        String zipFileName = "/Users/pankaj/sitemap.zip";
        
        File dir = new File("/Users/pankaj/tmp");
        String zipDirName = "/Users/pankaj/tmp.zip";
        
        zipSingleFile(file, zipFileName);
        
        ZipFiles zipFiles = new ZipFiles();
        zipFiles.zipDirectory(dir, zipDirName);
    }

    /**
     * This method zips the directory
     * @param dir
     * @param zipDirName
     */
    private void zipDirectory(File dir, String zipDirName) {
        try {
            populateFilesList(dir);
            //الآن نقوم بضغط الملفات واحداً تلو الآخر
            //إنشاء `ZipOutputStream` للكتابة إلى ملف zip
            FileOutputStream fos = new FileOutputStream(zipDirName);
            ZipOutputStream zos = new ZipOutputStream(fos);
            for(String filePath : filesListInDir){
                System.out.println("Zipping "+filePath);
                //بالنسبة لـ `ZipEntry`، نحتاج إلى الاحتفاظ بمسار الملف النسبي فقط، لذلك استخدمنا `substring` على المسار المطلق
                ZipEntry ze = new ZipEntry(filePath.substring(dir.getAbsolutePath().length()+1, filePath.length()));
                zos.putNextEntry(ze);
                //قراءة الملف وكتابته في `ZipOutputStream`
                FileInputStream fis = new FileInputStream(filePath);
                byte[] buffer = new byte[1024];
                int len;
                while ((len = fis.read(buffer)) > 0) {
                    zos.write(buffer, 0, len);
                }
                zos.closeEntry();
                fis.close();
            }
            zos.close();
            fos.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    
    /**
     * This method populates all the files in a directory to a List
     * @param dir
     * @throws IOException
     */
    private void populateFilesList(File dir) throws IOException {
        File[] files = dir.listFiles();
        for(File file : files){
            if(file.isFile()) filesListInDir.add(file.getAbsolutePath());
            else populateFilesList(file);
        }
    }

    /**
     * This method compresses the single file to zip format
     * @param file
     * @param zipFileName
     */
    private static void zipSingleFile(File file, String zipFileName) {
        try {
            //إنشاء `ZipOutputStream` للكتابة إلى ملف zip
            FileOutputStream fos = new FileOutputStream(zipFileName);
            ZipOutputStream zos = new ZipOutputStream(fos);
            //إضافة `Zip Entry` جديدة إلى `ZipOutputStream`
            ZipEntry ze = new ZipEntry(file.getName());
            zos.putNextEntry(ze);
            //قراءة الملف وكتابته في `ZipOutputStream`
            FileInputStream fis = new FileInputStream(file);
            byte[] buffer = new byte[1024];
            int len;
            while ((len = fis.read(buffer)) > 0) {
                zos.write(buffer, 0, len);
            }
            
            //إغلاق `Zip Entry` للكتابة في ملف zip
            zos.closeEntry();
            //إغلاق الموارد
            zos.close();
            fis.close();
            fos.close();
            System.out.println(file.getCanonicalPath()+" is zipped to "+zipFileName);
            
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

}

إخراج برنامج مثال الضغط في جافا أعلاه هو:

/Users/pankaj/sitemap.xml is zipped to /Users/pankaj/sitemap.zip
Zipping /Users/pankaj/tmp/.DS_Store
Zipping /Users/pankaj/tmp/data/data.dat
Zipping /Users/pankaj/tmp/data/data.xml
Zipping /Users/pankaj/tmp/data/xmls/project.xml
Zipping /Users/pankaj/tmp/data/xmls/web.xml
Zipping /Users/pankaj/tmp/data.Xml
Zipping /Users/pankaj/tmp/DB.xml
Zipping /Users/pankaj/tmp/item.XML
Zipping /Users/pankaj/tmp/item.xsd
Zipping /Users/pankaj/tmp/ms/data.txt
Zipping /Users/pankaj/tmp/ms/project.doc

لاحظ أنه أثناء تسجيل الملفات في ملف zip في الدليل، أقوم بطباعة المسار المطلق. ولكن أثناء إضافة `zip entry`، أستخدم المسار النسبي من الدليل بحيث عند فك الضغط عنه، سيتم إنشاء نفس هيكل الدليل. هذا كل شيء بالنسبة لمثال الضغط في جافا.

Source:
https://www.digitalocean.com/community/tutorials/java-zip-file-folder-example