Skip to content
Advertisement

ZipEntry is not writing file into directory

I am trying to write multiple files into a directory and a zip file. that directory and zip file are supposed to be contained in another zip. so my desired zip structure would look like this:

parent.zip
  - testDirectory/
  - testZip.zip

When I read my files into a byte[] and write them into my directory testDirectory nothing is written into the directory. the directory is empty when I open my zip.

On the other hand when I write my byte[] array into a zip file called testZip.zip the files will be correctly written into the zip file.

parent.zip, testDirectory/ and testZip.zip are all being created. the only problem is that testDirectory/ is empty.

What is the solution to my problem?

   private void addFiles(Document document, ZipOutputStream zos) throw FileNotFoundException, IOException {
     byte[] mediaFilesDirectory = getMediaFiles();
     
     ZipEntry entry = new ZipEntry(document.getId() + File.separator + "testDirectory/");
     entry.setSize(mediaFilesDirectory.length);
     zos.putNextEntry(entry);
     zos.write(mediaFilesDirectory);
     zos.closeEntry();
     
     ZipEntry entry2 = new ZipEntry(document.getId() + File.separator + "testZip.zip");
     entry2.setSize(mediaFilesDirectory.length);
     zos.putNextEntry(entry2);
     zos.write(mediaFilesDirectory);
     zos.closeEntry();
  }

 private byte[] getMediaFiles() throws FileNotFoundException {
    try (ByteArrayOutputStream baos = new ByteArrayOutputStream(); ZipOutputStream zos = new ZipOutputStream(baos)) {
        byte[] bytes = "Hello World".getBytes();
        String entryName = "test.txt";
        ZipEntry entry = new ZipEntry(entryName);
        entry.setSize(bytes.length);
        zos.putNextEntry(entry);
        zos.write(bytes);
        zos.closeEntry();
        zos.close();
        return baos.toByteArray();
    } catch (Exception exc) {
        throw new FileNotFoundException("Exception");
    }
}

No Exceptions are being thrown. If I comment out the ZipEntry for testDirectory/, then testZip.zip will still correctly be created. If I comment out testZip.zip, then testDirectory/ will still be empty.


Here some test code to run locally. it suffers from the same problem as my code:

import java.io.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

public class Main {
public static void main(String[] args) {
    System.out.println("Make sure to change the file variable");

    File file = new File("C:\Users\YourUser\test.zip"); //TODO enter a valid path here
    try(ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(file))) {
        addFiles(zos);
        zos.closeEntry();
    } catch (Exception e) {
        System.out.println(e);
    }
}

private static void addFiles(ZipOutputStream zos) throws Exception {
    byte[] mediaFilesDirectory = getMediaFiles();

    ZipEntry entry = new ZipEntry("1" + File.separator + "testDirectory/");
    entry.setSize(mediaFilesDirectory.length);
    zos.putNextEntry(entry);
    zos.write(mediaFilesDirectory);
    zos.closeEntry();

    ZipEntry entry2 = new ZipEntry("1" + File.separator + "testZip.zip");
    entry2.setSize(mediaFilesDirectory.length);
    zos.putNextEntry(entry2);
    zos.write(mediaFilesDirectory);
    zos.closeEntry();
}

private static byte[] getMediaFiles() throws Exception {
    try (ByteArrayOutputStream baos = new ByteArrayOutputStream(); ZipOutputStream zos = new ZipOutputStream(baos)) {
        byte[] bytes = "Hello World".getBytes();
        String entryName = "test.txt";
        ZipEntry entry = new ZipEntry(entryName);
        entry.setSize(bytes.length);
        zos.putNextEntry(entry);
        zos.write(bytes);
        zos.closeEntry();
        zos.close();
        return baos.toByteArray();
    }
}
}

Advertisement

Answer

ZipEntry entry = new ZipEntry(document.getId() + File.separator + "testDirectory/");
entry.setSize(mediaFilesDirectory.length);
zos.putNextEntry(entry);
zos.write(mediaFilesDirectory);
zos.closeEntry();

This code makes no sense.

It creates a directory, and directories do not themselves contain anything. In a zip file, a directory is just a string, a marker to the unzip tool: Make this dir.

A zip file is JUST a mapping of strings representing filenames to data representing the contents, that is it, zip files are not hierarchical.

If you want to write ‘foo.txt’ into the zip file as well as ‘subdir/bar.txt’, you would do:

ZipEntry entry = new ZipEntry("foo.txt");
zos.putNextEntry(entry);
zos.write(dataOfFooTxt);

ZipEntry entry = new ZipEntry("subdir/");
zos.putNextEntry(entry);

ZipEntry entry = new ZipEntry("subdir/bar.txt");
zos.putNextEntry(entry);
zos.write(dataOfBarTxt);

You just put an entry and do nothing further. Note also that zips always use forward slash for pathing, File.separator is something you should never use in java, except for one sole purpose: Creating strings fit to show to users. That’s all. forward slash is the path separator for java apps. Even if they run on windows.

What you are attempting to do (make a zip which you the nwant to put in a zip) would result in the command:

unzip myzip.zip

To unpack 2 files: ‘test.txt’ and ‘innerzip.zip’, which is, itself a zip file. This can be done but is really weird, and certainly doesn’t compress things any better. I’m not sure if that is your intent or if you’re just confused and you think this is how you put subdirs in zip files. If it’s the latter – just do what the second snippet in this answer does – do not make zips-in-zips.

User contributions licensed under: CC BY-SA
7 People found this is helpful
Advertisement