1

I converted a zip file of 5 files into a byte array. I want to output a zip file on my disk from that bytearray. My process was first reading the byte[] into a ByteArrayInputStream then into a ZipInputStream.

InputStream plainTextStream = new ByteArrayInputStream(plainText);
ZipInputStream zipInStream = new ZipInputStream(plainTextStream);

I want this to be outputted into a zip file on my disk so here I thought I will need a file and a ZipOutPutStream passing that zip file.

ZipOutputStream zipOutStream = new ZipOutputStream(new FileOutputStream(file));

With a zip entry I traversed the ZipInPutStream writing to a FileOutputStream each entry, using a buffer. At the end of each main loop I put an entry into the ZipOutPutStream.

    ZipEntry entry = null;
    while((entry = zipInStream.getNextEntry()) != null){
        FileOutputStream fileOutStream = new FileOutputStream(entry.getName());
        byte[] byteBuff = new byte[1024];
        int bytesRead = 0;
        while ((bytesRead = zipInStream.read(byteBuff)) != -1)
        {
            fileOutStream.write(byteBuff, 0, bytesRead);
        }
        fileOutStream.close();
        zipOutStream.putNextEntry(entry);
        zipInStream.closeEntry();
    }

I add the first file from the zip (there are 5 files), but when trying to add the 2nd file, I get an error on

zipOutStream.putNextEntry(entry)

java.util.zip.ZipException: invalid entry size (expected 18401 but got 0 bytes)

Through debugging I can't figure out where it goes wrong. I assume it may have something to do with the buffer when putting in the first outputstream(entry.getName())? The bytesRead while loop could be an issue. This is all assuming the logic makes sense. I hope I can approach a solution to this error.

AlMahiyan
  • 11
  • 1
  • 3
  • Unless you're editng the file, which you aren't in the code shown, decoding and recoding the input stream as ZIP is a completel waste of time. Just copy the original input stream to the file output stream. Your copy loop is OK except that presently you're writing to the wrong stream. Also you are assuming there are no directory entries in the input. – user207421 May 22 '21 at 00:39

2 Answers2

1

You never write the content of the zipped files to the zip output stream.

You don't need to write the output to a file stream, just write it directly to the zip output stream.

You should be using try-with-resources.

try (ZipInputStream zipInStream = new ZipInputStream(new ByteArrayInputStream(plainText));
     ZipOutputStream zipOutStream = new ZipOutputStream(new FileOutputStream(file));
) {
    byte[] byteBuff = new byte[1024];
    for (ZipEntry entry; (entry = zipInStream.getNextEntry()) != null; ) {
        zipOutStream.putNextEntry(entry);
        for (int bytesRead; (bytesRead = zipInStream.read(byteBuff)) != -1; ) {
            zipOutStream.write(byteBuff, 0, bytesRead);
        }
    }
}

There is no need to call closeEntry().

Andreas
  • 154,647
  • 11
  • 152
  • 247
  • I appreciate it. Why is closeEntry() not needed? I thought it was needed whenever an entry was put into the zipOutStream. Does putNextEntry(entry) remove the need? Also, the resulting zip has the same files but they are of different sizes, by some kb or so. Is that normal? – AlMahiyan May 22 '21 at 01:57
  • 1
    @AlMahiyan 1) Read the documentation of [`putNextEntry`](https://docs.oracle.com/javase/8/docs/api/java/util/zip/ZipOutputStream.html#putNextEntry-java.util.zip.ZipEntry-) --- 2) They might be using a different compression method or level. – Andreas May 22 '21 at 07:40
-3

To resolve (expected 18401 but got 0 bytes)

Create a new blank excel file.

Copy data from the file you copied from zip to the new created file in step 1.

Use the new file, it should work as its worked for me.

Thanks.

Ashish Gupta
  • 105
  • 1
  • 5