【问题标题】:Read a zip file inside zip file在 zip 文件中读取一个 zip 文件
【发布时间】:2019-02-25 15:43:23
【问题描述】:

我有一个 zip 文件,它位于 zip 文件的一个文件夹中,请建议我如何使用 zip 输入流读取它。

例如:

abc.zip
    |
      documents/bcd.zip

如何读取 zip 文件中的 zip 文件?

【问题讨论】:

  • 阅读是什么意思?要解压 bcd.zip 吗?

标签: java file zip unzip


【解决方案1】:

如果你想递归地查看 zip 文件中的 zip 文件,

    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();
        }
    }

使用从文件派生的文件输入流调用方法-

File file = new File(name);
lookupSomethingInZip(new FileInputStream(file));

【讨论】:

【解决方案2】:

以下代码 sn-p 列出了另一个 ZIP 文件中的 ZIP 文件的条目。根据您的需要进行调整。 ZipFile 在底层使用 ZipInputStreams

代码 sn-p 使用Apache Commons IO,具体为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");
}

【讨论】:

  • 太棒了 这就是我要找的。非常感谢兄弟
  • 完美的解决方案,正是我想要的,并且一起打破了我的头几个小时。你让我今天一整天都感觉很好。非常感谢。
  • 请注意,可以在没有临时文件的情况下执行此操作。您必须从"abc.zip" 文件中实例化一个原始ZipInputStream,然后为与文件"documents/bcd.zip" 对应的ZipEntry 打开一个新的ZipInputStream。确保用InputStream 包装原始ZipInputStream,以避免关闭由新ZipInputStream 管理的InputStream。您需要关闭的唯一InputStream 是原来的InputStream
  • 很好,但 3 Mb 仅适用于 IOUtils.copy 函数,它有 2 个字符串,严重吗?
【解决方案3】:

终于可以修复 Manas Maji 的答案了。最小解决方案:

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);
  }
}

注意:不要在递归方法中关闭流。

【讨论】:

    【解决方案4】:

    我编写了一个代码,可以将所有 zip 文件解压缩到一个 zip 文件中。它甚至可以解压缩到 n 级压缩。例如,如果您在 zip 中、在 zip 中(等等)有一个 zip 文件,它将提取所有文件。使用该类的 zipFileExtract 方法,并将源 zip 文件和目标目录作为参数传递。

    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());
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-12-04
      • 1970-01-01
      • 2012-03-09
      • 2016-06-15
      • 1970-01-01
      相关资源
      最近更新 更多