Read a zip file inside zip file
Asked Answered
P

4

12

I have zip file which is inside a folder in zip file please suggest me how to read it using zip input stream.

E.G.:

abc.zip
    |
      documents/bcd.zip

How to read a zip file inside zip file?

Pronoun answered 2/7, 2012 at 3:29 Comment(1)
what do you mean by read? do you want to extract bcd.zip?Mien
C
8

If you want to look through zip files within zip files recursively,

    public void lookupSomethingInZip(InputStream fileInputStream) throws IOException {
        ZipInputStream zipInputStream = new ZipInputStream(fileInputStream);
        String entryName = "";
        ZipEntry entry = zipInputStream.getNextEntry();
        while (entry!=null) {
            entryName = entry.getName();
            if (entryName.endsWith("zip")) {
                //recur if the entry is a zip file
                lookupSomethingInZip(zipInputStream);
            }
            //do other operation with the entries..

            entry=zipInputStream.getNextEntry();
        }
    }

Call the method with the file input stream derived from the file -

File file = new File(name);
lookupSomethingInZip(new FileInputStream(file));
Continuant answered 11/11, 2016 at 7:30 Comment(1)
I fixed broken recursion in this answer: https://mcmap.net/q/827638/-read-a-zip-file-inside-zip-file Thanks Manas Maji for idea :)Salazar
Q
5

The following code snippet lists the entries of a ZIP file inside another ZIP file. Adapt it to your needs. ZipFile uses ZipInputStreams underneath the hood.

The code snippet uses Apache Commons IO, specifically IOUtils.copy.

public static void readInnerZipFile(File zipFile, String innerZipFileEntryName) {
    ZipFile outerZipFile = null;
    File tempFile = null;
    FileOutputStream tempOut = null;
    ZipFile innerZipFile = null;
    try {
        outerZipFile = new ZipFile(zipFile);
        tempFile = File.createTempFile("tempFile", "zip");
        tempOut = new FileOutputStream(tempFile);
        IOUtils.copy( //
                outerZipFile.getInputStream(new ZipEntry(innerZipFileEntryName)), //
                tempOut);
        innerZipFile = new ZipFile(tempFile);
        Enumeration<? extends ZipEntry> entries = innerZipFile.entries();
        while (entries.hasMoreElements()) {
            ZipEntry entry = entries.nextElement();
            System.out.println(entry);
            // InputStream entryIn = innerZipFile.getInputStream(entry);
        }

    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        // Make sure to clean up your I/O streams
        try {
            if (outerZipFile != null)
                outerZipFile.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        IOUtils.closeQuietly(tempOut);
        if (tempFile != null && !tempFile.delete()) {
            System.out.println("Could not delete " + tempFile);
        }
        try {
            if (innerZipFile != null)
                innerZipFile.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

public static void main(String[] args) {
    readInnerZipFile(new File("abc.zip"), "documents/bcd.zip");
}
Quartersaw answered 2/7, 2012 at 4:25 Comment(3)
Perfect solution, exactly what i wanted and was breaking my head for hours together. You made my day. Thank you so much.Archives
Note that it is possible to do it without a temporary file. You will have to instantiate an original ZipInputStream from the "abc.zip" file then open a new ZipInputStream for the ZipEntry corresponding to the file "documents/bcd.zip". Make sure to wrap the original ZipInputStream with an InputStream that avoids closing the InputStream managed by the new ZipInputStream. The only InputStream you will need to close is the original one.Jansen
Great, but 3 Mb only for IOUtils.copy function, which have 2 strings, seriosly?Dori
S
3

Finally got it to work fixing Manas Maji's answer. Minimal solution:

import java.io.*;
import java.nio.file.*;
import java.util.zip.*;
import org.slf4j.*;

public void readZipFileRecursive(final Path zipFile) {
  try (final InputStream zipFileStream = Files.newInputStream(zipFile)) {
    this.readZipFileStream(zipFileStream);
  } catch (IOException e) {
    LOG.error("error reading zip file %s!", zipFile, e);
  }
}

private void readZipFileStream(final InputStream zipFileStream) {
  final ZipInputStream zipInputStream = new ZipInputStream(zipFileStream);
  ZipEntry zipEntry;
  try {
    while ((zipEntry = zipInputStream.getNextEntry()) != null) {
      LOG.info("name of zip entry: {}", zipEntry.getName());
      if (!zipEntry.isDirectory() && zipEntry.getName().endsWith(".zip")) {
        this.readZipFileStream(zipInputStream); // recursion
      }
    }
  } catch (IOException e) {
    LOG.error("error reading zip file stream", e);
  }
}

Care: don't close stream in recursive method.

Salazar answered 25/2, 2019 at 7:43 Comment(0)
L
1

I have written a code that can unzip all zip files inside a zip file. It can even unzip to n levels of compression. Like for example if you had a zip file inside a zip, inside a zip ( and so on) it would extract all of them. Use the zipFileExtract method of this class and pass the source zip file and destination directory as an argument.

import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

public class RecursiveFileExtract {
    private static final int BUFFER_SIZE = 4096;
    private static Queue<File> current;
    private static List<File> visited;

    public static void zipFileExtract(File sourceZipFile, File destinationDirectory) {
        Path temp = null;
        if(!destinationDirectory.exists())
        {
            destinationDirectory.mkdirs();
        }
        try {
            temp = Files.move(Paths.get(sourceZipFile.getAbsolutePath()), Paths.get(destinationDirectory.getAbsolutePath()+File.separator+sourceZipFile.getName()));
        } catch (IOException e) {
            e.printStackTrace();
        }
        File zipFile = new File(temp.toAbsolutePath().toString());
        current = new ConcurrentLinkedQueue<>();
        visited = new ArrayList<>();
        current.add(zipFile);
        do {
            unzipCurrent();
            zipFinder(destinationDirectory);
        }
        while (!current.isEmpty());
    }

    private static void zipFinder(File directory) {
        try {
            if (directory != null) {
                File fileArray[] = directory.listFiles();
                if (fileArray != null) {
                    for (File file : fileArray) {
                        if (file != null) {
                            if (file.isDirectory()) {
                                zipFinder(file);
                            } else {
                                if (file.getName().endsWith(".zip")) {
                                    if (!visited.contains(file)) {
                                        current.add(file);
                                    }
                                }
                            }
                        }
                    }
                }
            }
        } catch (Exception e) {
            System.out.println(e.getLocalizedMessage());
        }
    }

    private static void unzipCurrent() {
        try {
            while (!current.isEmpty()) {
                File file = current.remove();
                visited.add(file);
                File zipDirectory = new File(file.getParentFile().getAbsolutePath());
                unzip(file.getAbsolutePath(), zipDirectory.getAbsolutePath());
            }
        } catch (Exception e) {
            System.out.println(e.getLocalizedMessage());
        }
    }

    public static void unzip(String zipFilePath, String destDirectory) {
        try {
            ZipInputStream zipIn = new ZipInputStream(new FileInputStream(zipFilePath));
            ZipEntry entry = zipIn.getNextEntry();

            while (entry != null) {
                String filePath = destDirectory + File.separator + entry.getName();
                if (!entry.isDirectory()) {
                    extractFile(zipIn, filePath);
                } else {

                    File dir = new File(filePath);
                    Boolean result = dir.mkdir();
                }
                zipIn.closeEntry();
                entry = zipIn.getNextEntry();
            }
            zipIn.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static void extractFile(ZipInputStream zipIn, String filePath) {
        try {
            File file = new File(filePath);
            File parentFile = file.getParentFile();
            if (!parentFile.exists()) {
                Boolean result = parentFile.mkdirs();
                if (!result) {
                    throw new Exception();
                }
            }
            BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(filePath));
            byte[] bytesIn = new byte[BUFFER_SIZE];
            int read = 0;
            while ((read = zipIn.read(bytesIn)) != -1) {
                bos.write(bytesIn, 0, read);
            }
            bos.close();
        } catch (Exception e) {
           System.out.println(e.getLocalizedMessage());
        }
    }
}
Landslide answered 2/8, 2017 at 15:35 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.