मैं इस कोड का उपयोग कर रहा हूं (एंड्रॉइड 7.0/नौगेट) बाहरी भंडारण में एक ज़िप फ़ाइल को अनपैक करने के लिए (अंदर कई फ़ोल्डर स्तरों सहित):

try {
    ZipFile zip = new ZipFile(zippath);
    Enumeration enu = zip.entries();

    while(enu.hasMoreElements()) {
        ZipEntry zipEntry = (ZipEntry) enu.nextElement();
        BufferedInputStream bis = null;
        String fileName = null;

        try {
            fileName = zipEntry.getName();
            fileName = fileName.replace("\\",File.separator).replace("/",File.separator);
            int p = fileName.lastIndexOf(File.separator);

            if(p>=0) {
                File fd=new File(folderpath+File.separator+fileName.substring(0,p));
                fd.mkdirs();
            }

            BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(folderpath+File.separator+fileName));
            bis = new BufferedInputStream(zip.getInputStream(zipEntry));
            byte[] buffer = new byte[10000];
            int len = 0;

            while ((len = bis.read(buffer, 0, 10000)) > 0) {
                bos.write(buffer, 0, len);
            }

            bis.close();
            bos.close();
        } catch (IOException e1) {
            e1.printStackTrace();
            return;
        }
    }
} catch (IOException e2) {
    e2.printStackTrace();
}

एसडी कार्ड में लेखन पहुंच प्राप्त करने के लिए मैं createAccessIntent (स्टोरेज वॉल्यूम) का उपयोग कर रहा हूं जो सामान्य File के बजाय DocumentFiles का उपयोग करता है।

ZipInputStream पाने के लिए मैंने पहले ही ऐसा कर लिया है:

InputStream inputStream = this.getContentResolver().openInputStream(myDocumentFileZip.getUri());
BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream);
ZipInputStream zipInputStream = new ZipInputStream(bufferedInputStream);
ZipEntry zipEntry;

... और मैं अनुमान लगा रहा हूं कि आप इस तरह जारी रखते हैं:

while ((zipEntry = zipInputStream.getNextEntry()) != null) {

लेकिन आप वहां से क्या करते हैं - आप एसडी कार्ड पर फाइलों की प्रतिलिपि कैसे बनाते हैं और फिर भी ऊपर दिए गए कोड में फ़ोल्डर संरचना को कैसे रखते हैं लेकिन स्टोरेज वॉल्यूम (या स्टोरेज एक्सेस फ्रेमवर्क) का उपयोग करके क्या प्रदान करता है?

1
Neph 14 मई 2018, 14:55

1 उत्तर

सबसे बढ़िया उत्तर

स्टोरेज वॉल्यूम के साथ अनज़िप करें:

सावधान: यदि आप एक ही .zip फ़ाइल को कई बार अनज़िप करते हैं तो इस तरह यह प्रतियां बनाता है, जबकि पहली पोस्ट में मेरा मूल कोड (जिसे आप एसडी कार्ड के लिए उपयोग नहीं कर सकते) नहीं करता है, बल्कि इसके बजाय स्वचालित रूप से अधिलेखित हो जाता है!

try {
    InputStream is = getContentResolver().openInputStream(myZip.getUri());
    BufferedInputStream bis = new BufferedInputStream(is);
    ZipInputStream zis = new ZipInputStream(bis);
    ZipEntry zipEntry;

    while ((zipEntry = zis.getNextEntry()) != null) {
        String fileName = null; 

        try {
            fileName = zipEntry.getName();        
            fileName = fileName.replace("\\",File.separator).replace("/",File.separator);
            int p=fileName.lastIndexOf(File.separator);        
            DocumentFile destFolder = myDestFolder; //DocumentFile of the destination folder
            String destName = fileName;

            if (p>=0) {
                String[] split = fileName.split(File.separator);

                //If the .zip file contains multiple folder levels, this is where you  
                //have to check and then create them, e.g. for 3 levels:
                if(split.length==1) {
                    destFolder = myFolder;
                    destName = filename;
                } else if(split.length==2) {
                    if(mySubFolder==null) {
                        mySubFolder = myFolder.createDirectory(split[0]);
                    }

                    destFolder = mySubFolder;
                    destName = split[1];
                } else if(split.length==3) {
                    if(mySubFolder==null) {
                        mySubFolder = myFolder.createDirectory(split[0]);
                    }
                    if(mySubSubFolder==null) {
                        mySubSubFolder = mySubFolder.createDirectory(split[1]);
                    }

                    destFolder = mySubSubFolder;
                    destName = split[2];
                }
            }

            DocumentFile df = null;

            //Now you have to tell it what file extensions ("MIME" type) you want to use, e.g.:
            if(destName.endsWith(".txt")) {
                df = destFolder.createFile("text/plain",destName.substring(0,destName.length()-4));
            } else if(destName.endsWith(".jpg")) {
                df = destFolder.createFile("image/jpeg",destName.substring(0,destName.length()-4));
            }

            OutputStream out = getContentResolver().openOutputStream(df.getUri());
            BufferedOutputStream bos = new BufferedOutputStream(out);
            long zipfilesize = zipEntry.getSize();

            byte[] buffer = new byte[10000];
            int len = 0;
            int totlen = 0;

            while (((len = zis.read(buffer, 0, 10000)) > 0) && (totlen < zipfilesize)) {
                bos.write(buffer, 0, len);
                totlen += len;
            }

            bos.close();
        } catch (IOException e1) {
            e1.printStackTrace();
            return;
        }
    }

    is.close();
    bis.close();
    zis.close();
} catch (IOException e2) {
    e2.printStackTrace();
}

संपादित करें: महत्वपूर्ण: java.util.zip size या compressedSize सेट नहीं करता है ("-1" लौटाएगा), इसलिए यह कोड केवल फाइलों को बनाएगा लाइब्रेरी द्वारा बनाई गई ज़िप फ़ाइलों के साथ 0B का आकार - हाथ से बनाई गई ज़िप फ़ाइलें (उदाहरण के लिए WinRar के साथ) ठीक काम करती हैं। इसे ठीक करने के लिए, बदलें

while (((len = zis.read(buffer, 0, 10000)) > 0) && (totlen < zipfilesize)) {

साथ

while (((len = zis.read(buffer, 0, 10000)) > 0)) {

ऐसा करना संभव है क्योंकि:

ZipInputStream.getNextEntry() को कॉल प्रविष्टि की शुरुआत में इनपुटस्ट्रीम को स्थान देता है और इसलिए ZipInputStream की आपूर्ति ZipEntry के इनपुटस्ट्रीम की आपूर्ति के बराबर है।

स्रोत: https://stackoverflow.com/a/3233600/2016165

इसके साथ नुकसान (मेरे गैर-स्टोरेज वॉल्यूम संस्करण की तुलना में) यह है कि आप ए) ज़िप में फाइलों की कुल मात्रा नहीं प्राप्त कर सकते हैं और बी) फाइलों का (कुल) आकार भी नहीं प्राप्त कर सकते हैं, जिसका अर्थ है कि आप प्रगति पट्टी को "अनज़िपिंग..." संवाद में तब तक सेट नहीं कर सकते जब तक कि आप सभी ज़िप प्रविष्टियों को गिनने के लिए पहले पुनरावृति न करें।

1
Neph 28 मई 2018, 16:01