6

I'm trying to compress directory content into zip archive using java. Everything is fine, but I just want to clarify some facts. Here is the code which I use to compress files:

public void pack(@Nonnull String archiveName, @Nonnull File outputDir, @Nonnull File targetDir) {
  File zipFile = new File(outputDir, "out.zip");

  ZipOutputStream zipOutputStream = null;
  OutputStream outputStream;
  try {
    // create stream for writing zip archive
    outputStream = new FileOutputStream(zipFile);
    zipOutputStream = new ZipOutputStream(outputStream);
    // write files recursively
    writeFiles(zipOutputStream, targetDir.listFiles(), "");
  } catch (IOException e) {
    LOGGER.error("IO exception while packing files to archive", e);
  } finally {
    // close output streams
    if (zipOutputStream != null) {
      try {
        zipOutputStream.close();
      } catch (IOException e) {
        LOGGER.error("Unable to close zip output stream", e);
      }
    }
  }
}

/**
 * Writes specified files and their children (in case of directories) to archive
 *
 * @param zipOutputStream archive output stream
 * @param files           which should be added to archive
 * @param path            path relative of root of archive where files should be placed
 */
private void writeFiles(@Nonnull ZipOutputStream zipOutputStream, @Nullable File[] files, @Nonnull String path) throws IOException {
  if (files == null || files.length == 0) {
    return;
  }

  for (File file : files) {
    if (file.isDirectory()) {
      // recursively add files in this directory
      String fullDirectoryName = path + file.getName() + "/";
      File[] childFiles = file.listFiles();
      if (childFiles != null && childFiles.length > 0) {
        // write child files to archive. current directory will be created automatically
        writeFiles(zipOutputStream, childFiles, fullDirectoryName);
      } else {
        // empty directory. write directory itself to archive
        ZipEntry entry = new ZipEntry(fullDirectoryName);
        zipOutputStream.putNextEntry(entry);
        zipOutputStream.closeEntry();
      }
    } else {
      // put file in archive
      BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream(file));
      zipOutputStream.putNextEntry(new ZipEntry(path + file.getName()));
      ByteStreams.copy(bufferedInputStream, zipOutputStream);
      zipOutputStream.closeEntry();
      bufferedInputStream.close();
    }
  }
}

Now there are the questions:

  1. Is it correct that by default (and in my case too) I will get already compressed archive (using Deflate method)?

  2. How to get uncompressed archive:

    • If I set method zipOutputStream.setMethod(ZipOutputStream.STORED) I have to provide size, compressed size (is it will be equal to size?) and crc, otherwise I will get exceptions
    • If I don't want to calculate size and crc by myself I can use DEFLATE method with zero level:
      zipOutputStream.setMethod(ZipOutputStream.DEFLATED);
      zipOutputStream.setLevel(ZipOutputStream.STORED);
      So, is it correct that in this case I get not compressed archive at all?
    • Is there more convenient-obvious method to creating not-compressed archives?
ROMANIA_engineer
  • 54,432
  • 29
  • 203
  • 199
Gregory Kalabin
  • 1,760
  • 1
  • 19
  • 45
  • 3
    This [answer](http://stackoverflow.com/a/1207041/354831) may help you for the STORED. – Alexandre Lavoie Mar 13 '13 at 08:21
  • 1
    You could also consider `.tar` format instead of `.zip`, for uncompressed archive, depending on your use case. One lib for that: https://code.google.com/p/jtar/ – hyde Mar 13 '13 at 08:45

1 Answers1

-2

Rather than re-invent the wheel I'd seriously consider using an existing library for this, such as Apache Ant. The basic idiom for creating a zip file is:

Project p = new Project();
p.init();
Zip zip = new Zip();
zip.setProject(p);
zip.setDestFile(new File(outputDir, "out.zip"));
FileSet fs = new FileSet();
fs.setProject(p);
fs.setDirectory(targetDir);
zip.addFileset(fs);
zip.perform();

By default you will get a compressed archive. For an uncompressed zip all you need to add is

zip.setCompress(false);

after the setDestFile (in fact anywhere before the perform).

Ian Roberts
  • 120,891
  • 16
  • 170
  • 183