为什么ZipInputStream无法读取ZipOutputStream的输出?

8

我被这个Junit测试卡住了:

public void test() throws Exception {
    ByteArrayOutputStream out = new ByteArrayOutputStream();
    ZipOutputStream zipOut = new ZipOutputStream( out );
    zipOut.putNextEntry( new ZipEntry( "file" ) );
    zipOut.write( (new byte[] { 0x01, 0x02, 0x03 }) );
    zipOut.closeEntry();
    zipOut.close();

    ZipInputStream zipIn = new ZipInputStream( new ByteArrayInputStream( out.toByteArray() ) );
    ZipEntry entry = zipIn.getNextEntry();
    assertNotNull( entry );
    assertEquals( "file", entry.getName() );
    assertEquals( 3, entry.getSize() );
}

我正在使用ZipOutputStream写入文件名为“file”的文件,文件内容为3个字节。然后我尝试使用ZipInputStream读取创建的数据,但是最后一个assert失败了,因为entry.getSize()-1而不是预期的3
这里我做错了什么?我需要改变什么来恢复“file”的内容?我认为,首先我必须知道长度才能从流中读取数据。

尝试了你的代码 - 确实不起作用。我很困惑。正在调查中... - Peter Knego
5个回答

5

您需要实际阅读条目的内容,然后entry.getSize()将返回正确的大小。

要阅读条目,请使用:

    byte[] buf = new byte[1024];
    int len;
    while ((len = zipIn.read(buf)) > 0) {
        // use data;
    }

哦,太好了。在读取数据后,我错过了查看zipEntry的信息字段...谢谢你的提示! - tangens
2
问题在于,在 zipEntry 之前有一个 LOC 条目,而在 zipEntry 之后有一个 EXT 条目。两者都有一个大小字段。ZipOutputStream 总是在 LOC.size 中写入 0,而其他存档程序也会在 LOC 和 EXT 中写入大小。我想知道这可能会引起多少问题,并且如何使 ZipOutputStream 在 LOC 中写入大小? - rustyx

3
我自己找到了答案: entry 不包含正确的大小,但每次使用zipIn.getNextEntry()时,您会获得一个新的流来读取条目内容。因此,只需读取流直到结束,就可以获取条目的数据。
在我的JUnit测试中,最后一行可能是这样的:
byte[] restoredContent = new byte[ 10 ];
assertEquals( 3, zipIn.read( restoredContent ) );

现在一切都正常运作。

2

阅读ZipEntry的API文档。它说“如果已知”。您可以使用以下内容读取内容(它只打印zipentry的大小,根据需要更改处理数据):

ZipEntry entry = zipIn.getNextEntry();
int BUFSIZE = 1024;
byte [] buffer = new byte[BUFSIZE];
int read = 0;
int total = 0;
while( (read = zipIn.read(buffer, 0, BUFSIZE)) >0 ) { 
  total += read;
  // what do you want to do with the data read? Do it here
}   
System.err.println("Total: " + total);

0

我也遇到了同样的问题!

ZipInputStream无法读取ZipOutputStream的输出;

使用new ZipFile(file)会出现错误。

没有任何可能的解释!

档案查看器可以正常打开这个zip文件!

解决方案:嗯...它实际上并不是一个zip文件...而是一个名为“folder.zip”的tar文件。档案查看器足够聪明...

对于那些遇到这个问题的人:一定要仔细检查!!!


2
抱歉,你在说什么?你用ZipOutputStream写了一个TAR文件吗? - rustyx

0

最近我在读取使用ZipOutputStream创建的zip字节时遇到了类似的问题。

以下代码片段导致java.lang.NegativeArraySizeException异常。

zipEntry = zipInputStream.getNextEntry();
byte[] bytes = new byte[(int) zipEntry.getSize()];

一个快速的解决方案是使用Apache commons-io IOUtils读取当前条目的所有字节。
zipEntry = zipInputStream.getNextEntry();
byte[] bytes = org.apache.commons.io.IOUtils.toByteArray(zipInputStream);

我希望这对某人有所帮助。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接