Java: Zipinputstream to Zipoutputstream leads to "end-of-central-directory signature not found" Error
Asked Answered
F

2

6

I try to copy a Zip from a Zipinputstream to a Zipoutputstream.

I store the Zip as byte[] in a Oracle database. I use Zipinputstream to decompress the zip (later I want to edit the Zip) and then put it into a Zipoutputstream to get a new byte[] and use this array to download the file later via a ServletOutputStream. When I create a new file - without the Zipinputstream - it works. But when I use the Zipinputstream I get the error.

Here is my code:

        ZipInputStream zipInputStream = new ZipInputStream(new ByteArrayInputStream(fileFromDataBase),
                Charset.forName("UTF-8"));
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        ZipOutputStream zos = new ZipOutputStream(byteArrayOutputStream, Charset.forName("UTF-8"));
        ZipEntry currentEntry;
        byte[] buffer = new byte[8192];
        while ((currentEntry = zipInputStream.getNextEntry()) != null) {
            ZipEntry newEntry = new ZipEntry(currentEntry.getName());
            zos.putNextEntry(newEntry);
            int length;
            while ((length = zipInputStream.read(buffer)) > 0) {
                zos.write(buffer, 0, length);
            }
            zos.closeEntry();                   
        }

        //TO Object to download later the Zipfile from html page
        paketDownloadTO = new PaketDownloadTO();
        paketDownloadTO.setData(byteArrayOutputStream.toByteArray());
        paketDownloadTO.setFileName(fileName);

        zos.finish();
        zipInputStream.close();
        zos.close();
Farcy answered 2/12, 2016 at 8:39 Comment(2)
Why? Just copy the bytes. You don't need all this complication.Description
Because I later need to edit the zip (put new files into, delete some etc) But if plain copy is not working, then I cant edit it.Farcy
U
8

My guess is that You should do zos.close() before byteArrayOutputStream.close().

UPDATE:

and move:

paketDownloadTO = new PaketDownloadTO();
paketDownloadTO.setData(byteArrayOutputStream.toByteArray());
paketDownloadTO.setFileName(fileName);

after zos.close();

Usury answered 2/12, 2016 at 8:55 Comment(2)
In fact instead of ByteArrayOutputStream.close() which is redundant if a stream wrapping it has been closed.Description
Both do not fix the problem :-(Farcy
E
0

The problem is, calling byteArrayOutputStream.toByteArray() before calling zipInputStream.close()

The ZipInputStream only write the end-of-central-directory when close is called, because before that it does not know if you're going to add new entries or not.

But since byteArrayOutputStream.toByteArray() returns a copy of the byte array at the time you're calling it. It does not contains the end-of-central-directory, which is written to the stream at a later time.

Epileptoid answered 29/4, 2022 at 15:3 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.