简体   繁体   中英

Why ZipInputStream can't read the output of ZipOutputStream?

I'm stuck with this junit test:

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

I'm writing a file with the name "file" and a content of three bytes to a ZipOutputStream. Then I try to read the created data with a ZipInputStream, but the last assert fails, because entry.getSize() is -1 and not 3 , as expected.

What am I doing wrong here? What do I have to change to restore the content of "file"? I think, I first have to know the length to be able to read the data from the stream?

You actually have to read the contents of the entry, then entry.getSize() will return the correct size.

To read entry use:

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

I found the answer by myself: entry does not contain the correct size, but with each zipIn.getNextEntry() you get a fresh stream to read the content of your entry from. So simply read the stream up to the end and you have the data of your entry.

In my junit test the last line could look like this:

byte[] restoredContent = new byte[ 10 ];
assertEquals( 3, zipIn.read( restoredContent ) );

Now everything works fine.

Read API doc for ZipEntry. It says "if known". You can read the content using the following (it just prints the size of the zipentry, change it process data appropriately):

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

Recently I had a similar problem while reading a zip bytes created using ZipOutputStream.

The following snippet led to java.lang.NegativeArraySizeException.

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

An quick solution it was to use Apache commons-io IOUtils to read the all bytes of current entry.

zipEntry = zipInputStream.getNextEntry();
byte[] bytes = org.apache.commons.io.IOUtils.toByteArray(zipInputStream);

I hope this will be helpful to someone.

Same problem here!

ZipInputStream can't read the output of ZipOutputStream;

new ZipFile(file) fails with an error

no possible explanation!

Archive viewer program opens the zip file just fine!

SOLUTION: Uh... it wasn't a zip file after all... it was a tar called 'folder.zip'. Archive viewer was smart enough...

To those with this problem: Double check!!!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM