首页 > 解决方案 > 无法从 ZIP 文件输入流中读取文件

问题描述

我有一个要阅读的 Zip 文件。我不想使用 a ZipFile,因为将来我想对不是来自文件的数据执行此操作。

这是我到目前为止所尝试的。它不打印 的内容res00000.dat,而是打印一个空行。我不知道如何解决这个问题

ZipInputStream zipInputStream = new ZipInputStream(inputStream);
ZipEntry zipEntry;
while ((zipEntry = zipInputStream.getNextEntry()) != null) {
    if (!zipEntry.getName().equals("res00000.dat")) {
        zipInputStream.closeEntry();
        continue;
    }
}
int len;
ByteArrayOutputStream byteArrayOutputStream = new ByterrayOutputStream();
byte[] buffer = new byte[1024];
while ((len = zipInputStream.read(buffer)) > 0) {
    byteArrayOutputStream.write(buffer, 0, len);
}
String xml = byteArrayOutputStream.toString();
System.out.println(xml);
zipInputStream.closeEntry();
zipInputStream.close();
return null;

我的 ZIP 文件中只有两个文件。这是我试图解析的 Blackboard Test bank 文件:

Zip file
+-imsmanifest.xml
+-res00000.dat

有人可以帮忙吗?

标签: javazipunzipzipfile

解决方案


您的代码当前不处理丢失的条目。它只是默默地滚动到 a 的末尾,ZipInputStream所以没有办法知道发生了什么。当名称标识的条目丢失时,您可以执行以下操作以获取异常:

public String readEntry(ZipInputStream in, String name) {
  while ((zipEntry = in.getNextEntry()) != null) {
    if (zipEntry.getName().equals(name)) {
      return readXml(zipInputStream);
    }
  }
  throw new IllegalStateException(name + " not found inside ZIP");
}

IllegalStateException现在很可能会在上面观察到缺少res00000.dat.

请注意,在滚动时没有理由closeEntry()手动调用,ZipInputStream因为getNextEntry()它已经在引擎盖下进行了。来自 JDK 11 源代码:

public ZipEntry getNextEntry() throws IOException {
    ensureOpen();
    if (entry != null) {
        closeEntry();
    }
    ...

推荐阅读