javatry-with-resourceszipoutputstream

Java - ZipOutputStream within try-with-resources


I have this Java code that creates and saves a zip file with a text file inside it:

public static void main(String[] args) {
    try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
         ZipOutputStream zos = new ZipOutputStream(baos)) {
        String s = "Hello, world!";
        ZipEntry entry = new ZipEntry("text_file.txt");
        zos.putNextEntry(entry);
        zos.write(s.getBytes());
        zos.closeEntry();

        try (OutputStream os = new FileOutputStream("zip_file.zip")) {
            baos.writeTo(os);
            System.out.println("ZIP file created successfully");
        }
    } catch (IOException e) {
        System.out.println("Error: " + e);
    }
}

The problem with this code is that it creates a zip file that is corrupted, so I cannot extract or even open the content within it.

Eventually I found out that if I manually close the ZipOutputStream by putting zos.close() after zos.closeEntry() the zip file is created successfully without corruption. Honestly this does not make any sense to me since I have declared the ZipOutputStream inside a try-with-resource statement, so I would have expected it to close automatically.

So it seems that the try-with-resource statement does not actually close the stream. Am I doing something wrong?

Any help would be appreciated.

OS: Windows 10

Note: I used ByteArrayOutputStream because in the real scenario I have to create the zip file in memory, since I don't have a folder on a disk to rely on.


Solution

  • It turned out that I was misplacing the ByteArrayOutputStream object: I should have not closed it by placing it inside the try-with-resource statement because, as explained here, ByteArrayOutputStream is purely memory based so the allocated memory will be released automatically by the garbage collector.

    The following code produces the desired result:

    public static void main(String[] args) {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
    
        try (ZipOutputStream zos = new ZipOutputStream(baos)) {
            String s = "Hello, world!";
            ZipEntry entry = new ZipEntry("text_file.txt");
            zos.putNextEntry(entry);
            zos.write(s.getBytes());
            zos.closeEntry();
        } catch (IOException e) {
            System.out.println("Error: " + e);
        }
    
        try (OutputStream os = new FileOutputStream("zip_file.zip")) {
            baos.writeTo(os);
            System.out.println("ZIP file created successfully");
        } catch (IOException e) {
            System.out.println("Error: " + e);
        }
    }