Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why ZipInputStream can't read the output of ZipOutputStream?

Tags:

java

zip

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?

like image 889
tangens Avatar asked Nov 12 '10 21:11

tangens


2 Answers

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;
    }
like image 76
Peter Knego Avatar answered Nov 10 '22 13:11

Peter Knego


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.

like image 35
tangens Avatar answered Nov 10 '22 13:11

tangens