फ़ाइलों को ज़िप / ज़िप करने के लिए एक अच्छा जावा पुस्तकालय क्या है? [बन्द है]


232

मैंने JDK और Apache कम्प्रेशन लिब के साथ आने वाले डिफॉल्ट जिप लाइब्रेरी को देखा और मैं उनसे 3 साल से नाखुश हूं:

  1. वे फूला हुआ है और खराब एपीआई डिजाइन है। मुझे बॉयलर प्लेट बाइट एरे आउटपुट, ज़िप इनपुट, फाइल आउट स्ट्रीम और संबंधित प्रासंगिक धाराएँ और अपवादों को पकड़ने और बाइट बफ़र्स को अपने दम पर लिखने की ५० पंक्तियाँ लिखनी हैं ? मेरे पास एक साधारण एपीआई क्यों नहीं है जो इस तरह दिखता है Zipper.unzip(InputStream zipFile, File targetDirectory, String password = null)और Zipper.zip(File targetDirectory, String password = null)यह सिर्फ काम करता है?

  2. ऐसा लगता है कि ज़िप खोलना फ़ाइल मेटा-डेटा को नष्ट कर देता है और पासवर्ड हैंडलिंग टूट जाती है।

  3. इसके अलावा, मेरे द्वारा कोशिश की गई सभी लाइब्रेरीज़ UNIX के साथ मिलने वाली कमांड लाइन जिप टूल्स की तुलना में 2-3x धीमी थीं?

मेरे लिए (2) और (3) मामूली बिंदु हैं, लेकिन मैं वास्तव में एक-लाइन इंटरफ़ेस के साथ एक अच्छा परीक्षण किया गया पुस्तकालय चाहता हूं।


13
# 1 के लिए, यह इसलिए है क्योंकि हर कोई किसी फ़ाइल को किसी निर्देशिका में अनज़िप नहीं कर रहा है। आप हमेशा एक ही पैटर्न का उपयोग कर रहे हैं, तो क्यों नहीं सिर्फ एक उपयोगिता वर्ग है कि दूसरों से एक लपेटता है और करता कुछ लिखते हैं वह आप इसे करने की जरूरत है और सिर्फ का उपयोग कि ?
एडवर्ड थॉमसन

14
@EdwardThomson क्योंकि कोड लिखना, परीक्षण कोड, और कोड बनाए रखने की तुलना में लाइब्रेरी का उपयोग करना आसान है।
ज़क

11
@EdwardThomson: आपका तर्क अमान्य है। Python zip API देखें: docs.python.org/3/library/zipfile । आपको ज़िप या अनज़िप फ़ाइलों के लिए कोड की 1 पंक्ति चाहिए। एपीआई को सामान्य मामले को बहुत अच्छी तरह से संभालना चाहिए और मैं ज़िपिंग या ज़िपिंग के अलावा ज़िप एपीआई के किसी भी उपयोग के मामले के बारे में नहीं सोच सकता।
पथिक

7
@wrick: ज़िप करने के लिए एक फ़ाइल या अनज़िप करने के लिए एक फ़ाइल ज़िप करने या एक धारा अनज़िप करने का एक विशेष मामला है। यदि आपका एपीआई मुझे इसकी एक धारा लिखने नहीं देता है और इसके बजाय मुझे एक फाइल के लिए एक धारा लिखने के लिए इतना है कि मैं अपने एपीआई के लिए फ़ीड कर सकते हैं, तो अपने एपीआई मस्तिष्क क्षतिग्रस्त है।
एडवर्ड थॉमसन

52
@EdwardThomson - ठीक है, इसलिए लाइब्रेरी को फाइल और स्ट्रीम दोनों का समर्थन करें। यह हर किसी के समय की बर्बादी है - मेरा, आपका, पूछने वाला, और अन्य सभी गोगलर्स जो इस बात पर अड़ेंगे कि हम सभी को अपनी-अपनी जिप यूटिलिटीज को लागू करना होगा। जैसे DRY होता है, वैसे ही DROP होता है - Do Not दोहराएँ अन्य लोग।
आर्टऑफवर्फ

जवाबों:


291

मुझे पता है कि इसकी देर हो चुकी है और बहुत सारे उत्तर हैं लेकिन यह zip4j मेरे द्वारा उपयोग की जाने वाली ज़िपिंग के लिए सर्वश्रेष्ठ पुस्तकालयों में से एक है। इसका सरल (कोई बॉयलर कोड नहीं) और पासवर्ड से सुरक्षित फ़ाइलों को आसानी से संभाल सकते हैं।

import net.lingala.zip4j.exception.ZipException;
import net.lingala.zip4j.core.ZipFile;


public static void unzip(){
    String source = "some/compressed/file.zip";
    String destination = "some/destination/folder";
    String password = "password";

    try {
         ZipFile zipFile = new ZipFile(source);
         if (zipFile.isEncrypted()) {
            zipFile.setPassword(password);
         }
         zipFile.extractAll(destination);
    } catch (ZipException e) {
        e.printStackTrace();
    }
}

मावेन निर्भरता है:

<dependency>
    <groupId>net.lingala.zip4j</groupId>
    <artifactId>zip4j</artifactId>
    <version>1.3.2</version>
</dependency>

1
मुझे org.zeroturnaround.zip.ZipException: java.io.FileNotFoundException: छवियाँ \ 001GL.JPG मिली: खुली विफल: EINVAL (अमान्य तर्क) त्रुटि
Smit Patel

4
क्या यह एंड्रॉइड के साथ काम करता है?
Ercan

1
नहीं, यह Android के साथ ठीक काम नहीं कर रहा है, इसका चीनी भाषा का समर्थन नहीं है।
धीरज हिमानी

3
Zip4J एक इनपुटस्ट्रीम से केवल डिस्क से जिप पढ़ने का समर्थन नहीं करता है।
रेनॉड सेराटो

2
वेबसाइट पर एक javadoc नहीं है।
जॉन्स डेसी

76

साथ अपाचे कॉमन्स-आईओ 's IOUtilsआप यह कर सकते हैं:

try (java.util.zip.ZipFile zipFile = new ZipFile(file)) {
  Enumeration<? extends ZipEntry> entries = zipFile.entries();
  while (entries.hasMoreElements()) {
    ZipEntry entry = entries.nextElement();
    File entryDestination = new File(outputDir,  entry.getName());
    if (entry.isDirectory()) {
        entryDestination.mkdirs();
    } else {
        entryDestination.getParentFile().mkdirs();
        try (InputStream in = zipFile.getInputStream(entry);
             OutputStream out = new FileOutputStream(entryDestination)) {
            IOUtils.copy(in, out);
        }
    }
  }
}

यह अभी भी कुछ बॉयलरप्लेट कोड है, लेकिन इसमें केवल 1 गैर-विदेशी निर्भरता है: कॉमन्स-आईओ


1
@VitalySazanovich आप Java 7 ZipEntry का उल्लेख कर रहे हैं।
रैंडी

2
धन्यवाद। इसके अलावा अंत में zipFile.close () की जरूरत है।
जोशुआ

4
IOUtils.closeQuietly (आउट) क्यों नहीं?
जुआन मेंडेज़

2
@JuanMendez क्योंकि यदि पास में त्रुटियां हैं, तो आप यह सुनिश्चित नहीं कर सकते कि फ़ाइल पूरी तरह से और सही तरीके से सहेजी गई थी। लेकिन इसके अलावा सामान्य करने के लिए close()यह चोट नहीं होगा।
vadipp

3
यह समाधान ज़िपस्लिप के लिए असुरक्षित है (zip4j भी प्रभावित है )
Marcono1234

40

केवल JDK का उपयोग करके ज़िप फ़ाइल और उसके सभी सबफ़ोल्डर्स को निकालें:

private void extractFolder(String zipFile,String extractFolder) 
{
    try
    {
        int BUFFER = 2048;
        File file = new File(zipFile);

        ZipFile zip = new ZipFile(file);
        String newPath = extractFolder;

        new File(newPath).mkdir();
        Enumeration zipFileEntries = zip.entries();

        // Process each entry
        while (zipFileEntries.hasMoreElements())
        {
            // grab a zip file entry
            ZipEntry entry = (ZipEntry) zipFileEntries.nextElement();
            String currentEntry = entry.getName();

            File destFile = new File(newPath, currentEntry);
            //destFile = new File(newPath, destFile.getName());
            File destinationParent = destFile.getParentFile();

            // create the parent directory structure if needed
            destinationParent.mkdirs();

            if (!entry.isDirectory())
            {
                BufferedInputStream is = new BufferedInputStream(zip
                .getInputStream(entry));
                int currentByte;
                // establish buffer for writing file
                byte data[] = new byte[BUFFER];

                // write the current file to disk
                FileOutputStream fos = new FileOutputStream(destFile);
                BufferedOutputStream dest = new BufferedOutputStream(fos,
                BUFFER);

                // read and write until last byte is encountered
                while ((currentByte = is.read(data, 0, BUFFER)) != -1) {
                    dest.write(data, 0, currentByte);
                }
                dest.flush();
                dest.close();
                is.close();
            }


        }
    }
    catch (Exception e) 
    {
        Log("ERROR: "+e.getMessage());
    }

}

ज़िप फ़ाइलें और उसके सभी सबफ़ोल्डर:

 private void addFolderToZip(File folder, ZipOutputStream zip, String baseName) throws IOException {
    File[] files = folder.listFiles();
    for (File file : files) {
        if (file.isDirectory()) {
            addFolderToZip(file, zip, baseName);
        } else {
            String name = file.getAbsolutePath().substring(baseName.length());
            ZipEntry zipEntry = new ZipEntry(name);
            zip.putNextEntry(zipEntry);
            IOUtils.copy(new FileInputStream(file), zip);
            zip.closeEntry();
        }
    }
}

7
बंद करने के लिए कॉल बहुत कम से कम "अंत" ब्लॉक के अंदर होना चाहिए। अपवादों को अच्छी तरह से संभाला नहीं जाता है। -> मुझे लगता है कि ओपी ने पुस्तकालय का उपयोग करने के लिए क्यों कहा इसका हिस्सा है ।

4
यह बहुत अधिक कोड है। यह 2 लाइनों में किया जा सकता है।
मक्की

/mnt/sdcard/final_unzip_data/Product_images\001GL.JPG: खुली विफल: EINVAL (अमान्य तर्क)
Smit Patel

@Joe माइकल इसे पोस्ट करने के लिए धन्यवाद दोस्त। यह मेरी समस्या का समाधान करता है। मैं extractFolder(String zipFile,String extractFolder)
u01 को

यह कोड फ़ाइल विशेषताओं और अनुमतियों को नहीं रखता है ... यदि आप इस तरह का उपयोग करते हैं कि एक रनने योग्य एप्लिकेशन को अनज़िप कर सकते हैं, तो फ़ाइल अनुमतियों के बारे में अजीब त्रुटियों के लिए तैयार रहें। इससे मुझे एक हफ्ते का सिरदर्द हो गया है।
रेनाटो

23

एक अन्य विकल्प जिसे आप देख सकते हैं वह है जेवी-जिप मावेन केंद्रीय और परियोजना पृष्ठ से https://github.com/zeroturnaround/zt-zip पर उपलब्ध

इसमें मानक पैकिंग और अनपैकिंग कार्यक्षमता (स्ट्रीम पर और फाइल सिस्टम पर) + बहुत सारी सहायक विधियाँ हैं जो संग्रह में फ़ाइलों के परीक्षण के लिए या प्रविष्टियों को जोड़ने / हटाने के लिए हैं।


17

ज़िप के लिए पूर्ण कार्यान्वयन / zip4j के साथ एक फ़ोल्डर / फ़ाइल खोलना


जार को यहां से डाउनलोड करें , और इसे अपने प्रोजेक्ट बिल्ड पथ में जोड़ें। classBellow सेक और साथ या पासवर्ड के बिना किसी भी फ़ाइल या फ़ोल्डर निकाल सकते हैं संरक्षण

import java.io.File;
import net.lingala.zip4j.model.ZipParameters;
import net.lingala.zip4j.util.Zip4jConstants;
import net.lingala.zip4j.core.ZipFile;  

public class Compressor {
    public static void zip(String targetPath, String destinationFilePath, String password) {
        try {
            ZipParameters parameters = new ZipParameters();
            parameters.setCompressionMethod(Zip4jConstants.COMP_DEFLATE);
            parameters.setCompressionLevel(Zip4jConstants.DEFLATE_LEVEL_NORMAL);

            if(password.length()>0){
                parameters.setEncryptFiles(true);
                parameters.setEncryptionMethod(Zip4jConstants.ENC_METHOD_AES);
                parameters.setAesKeyStrength(Zip4jConstants.AES_STRENGTH_256);
                parameters.setPassword(password);
            }

            ZipFile zipFile = new ZipFile(destinationFilePath);

            File targetFile = new File(targetPath);
            if(targetFile.isFile()){
                zipFile.addFile(targetFile, parameters);
            }else if(targetFile.isDirectory()){
                zipFile.addFolder(targetFile, parameters);
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void unzip(String targetZipFilePath, String destinationFolderPath, String password) {
        try {
            ZipFile zipFile = new ZipFile(targetZipFilePath);
            if (zipFile.isEncrypted()) {
                zipFile.setPassword(password);
            }
            zipFile.extractAll(destinationFolderPath);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**/ /// for test only
    public static void main(String[] args) {

        String targetPath = "target\\file\\or\\folder\\path";
        String zipFilePath = "zip\\file\\Path"; 
        String unzippedFolderPath = "destination\\folder\\path";
        String password = "your_password"; // keep it EMPTY<""> for applying no password protection

        Compressor.zip(targetPath, zipFilePath, password);
        Compressor.unzip(zipFilePath, unzippedFolderPath, password);
    }/**/
}

1
एक अच्छा जवाब और पुस्तकालय। निकाला जा रहा है 1868 फ़ाइलों 20+ मिनट (किसी कारण से) ZipInputStream का उपयोग करते समय की तुलना में, इस पुस्तकालय पर ~ 15 सेकंड लगे
Jonty800

8

एक बहुत अच्छा प्रोजेक्ट TrueZip है

TrueZIP वर्चुअल फ़ाइल सिस्टम (VFS) के लिए एक जावा आधारित प्लग-इन फ्रेमवर्क है, जो आर्काइव फ़ाइलों को पारदर्शी पहुंच प्रदान करता है जैसे कि वे सिर्फ नई डायरेक्टरी

उदाहरण के लिए ( वेबसाइट से ):

File file = new TFile("archive.tar.gz/README.TXT");
OutputStream out = new TFileOutputStream(file);
try {
   // Write archive entry contents here.
   ...
} finally {
   out.close();
}

पुस्तकालय अच्छा लग रहा है - फिर भी यह स्पष्ट नहीं है कि एक ज़िपपिनस्ट्रीम / फ़ाइल / पथ को दिए गए ज़िप-फ़ाइल को बस कैसे अनज़िप किया जाए।
पथिक

1
ट्रूज़िप बहुत अच्छी तरह से धाराओं से पढ़ने को संभालने के लिए नहीं लगता है।
टेओ क्लेस्ट्रुप रोइज्जन जू

5
क्या यह काफी हद तक वैसा ही नहीं है जैसा कि आप जावा 7 में कर सकते हैं? ( ZipFileSystemProvider देखें )।
पीटर

1
@peterh: मानक- JDK ज़िपफिलेसिस्टमप्रॉइडर एक अच्छा जवाब होगा। कम ही लोग इसे टिप्पणी के रूप में देखते हैं।
इयुज़

3

एक अन्य विकल्प JZlib है । मेरे अनुभव में, यह zip4J की तुलना में कम "फ़ाइल-केंद्रित" है, इसलिए यदि आपको फ़ाइलों के बजाय इन-मेमोरी ब्लब्स पर काम करने की आवश्यकता है, तो आप इसे देख सकते हैं।



0

क्या आपने http://commons.apache.org/vfs/ पर एक नज़र डाली है ? यह आपके लिए बहुत सी चीजों को सरल बनाने का दावा करता है। लेकिन मैंने इसे किसी प्रोजेक्ट में इस्तेमाल नहीं किया है।

मुझे JDK या Apache कम्प्रेशन के अलावा जावा-नेटिव कम्प्रेशन लिब के बारे में भी जानकारी नहीं है।

मुझे याद है कि एक बार जब हमने अपाचे चींटी से कुछ सुविधाएँ छीनी थीं - उनमें कम्प्रेशन / डीकंप्रेसन के लिए बहुत सारे बर्तन थे।

VFS के साथ नमूना कोड इस तरह दिखेगा:

File zipFile = ...;
File outputDir = ...;
FileSystemManager fsm = VFS.getManager();
URI zip = zipFile.toURI();
FileObject packFileObject = fsm.resolveFile(packLocation.toString());
FileObject to = fsm.toFileObject(destDir);
FileObject zipFS;
try {
    zipFS = fsm.createFileSystem(packFileObject);
    fsm.toFileObject(outputDir).copyFrom(zipFS, new AllFileSelector());
} finally {
    zipFS.close();
}

1
वीएफएस सामान में ज़िप फ़ाइलों के लिए समर्थन अपने आप में बहुत सीमित लगता है: commons.apache.org/vfs/filesystems.html
TJ Crowder
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.