多次使用ZipInputStream.getNextEntry()时出现问题

时间:2018-04-18 23:23:13

标签: java android zip

我正在尝试从zip解压缩特定文件。我首先得到ZipInputStream

ZipInputStream zipIn = new ZipInputStream(new BufferedInputStream(new FileInputStream(filePath)));

好的,这个有效!现在我想提取两个名为F1和F2的文件,所以我打电话给

extractFileFromZip(zipIn, Path + "F1", "F1")
extractFileFromZip(zipIn, Path + "F2", "F2")

public static boolean extractFileFromZip(ZipInputStream inZip, String file, String name) throws Exception {
    byte data[] = new byte[BUFFER_SIZE];

    boolean found = false;

    ZipEntry ze;
    while((ze = inZip.getNextEntry()) != null) {
        if(ze.getName().equals(name)) {
            found = true;
            // delete old file first
            File oldFile = new File(file);
            if(oldFile.exists()) {
                if(!oldFile.delete()) {
                    throw new Exception("Could not delete " + file);
                }
            }

            FileOutputStream outFile = new FileOutputStream(file);
            int count = 0;
            while((count = inZip.read(data)) != -1) {
                outFile.write(data, 0, count);
            }

            outFile.close();
            //inZip.closeEntry();
        }
    }
    return true;
}

现在问题在于inZip.getNextEntry()。对于F1,它将正确循环遍历所有文件,然后给出null。但是对于F2,它只会给null

为什么会这样?

2 个答案:

答案 0 :(得分:1)

您正在扫描整个流,并将其消耗掉。当你第二次尝试这样做时,流已经在结束,所以什么都不做。

此外,如果你只需要一小部分字符串,那么流式传输zip文件中的所有字节都很慢。

使用ZipFile代替,因为它允许随机访问zip条目,因此它更快,并且允许以随机顺序读取条目。

注意:以下代码已更改为使用Java 7+功能以更好地处理错误,例如try-with-resourcesNIO.2

ZipFile zipFile = new ZipFile(filePath);
extractFileFromZip(zipFile, path + "F1", "F1");
extractFileFromZip(zipFile, path + "F2", "F2");

public static boolean extractFileFromZip(ZipFile zipFile, String file, String name) throws IOException {
    ZipEntry ze = zipFile.getEntry(name);
    if (ze == null)
        return false;
    Path path = Paths.get(file);
    Files.deleteIfExists(path);
    try (InputStream in = zipFile.getInputStream(ze)) {
        Files.copy(in, path);
    }
    return true;
}

或者,仅将其流式传输一次,然后在while循环中检查这两个名称。

Map<String, String> nameMap = new HashMap<>();
nameMap.put("F1", path + "F1");
nameMap.put("F2", path + "F2");
extractFilesFromZip(filePath, nameMap);

public static void extractFilesFromZip(String filePath, Map<String, String> nameMap) throws IOException {
    try (ZipInputStream zipIn = new ZipInputStream(new BufferedInputStream(new FileInputStream(filePath)))) {
        for (ZipEntry ze; (ze = zipIn.getNextEntry()) != null; ) {
            String file = nameMap.get(ze.getName());
            if (file != null) {
                Path path = Paths.get(file);
                Files.deleteIfExists(path);
                Files.copy(zipIn, path);
            }
        }
    }
}

答案 1 :(得分:0)

因为您读取整个流以提取F1。所以下次,对于F2,getNextEntry()返回null。您需要重新打开zip流,或者更好的是,传递一个文件列表以解压缩到您的方法。