Welcome to Our Blog

ZeroTurnaround releases YAZLJ (Yet Another Zip Library for Java)



What, another ZIP abstraction?

During the development of ZeroTurnaround products we have had a growing need to uncompress and compress ZIP archives. For example, JRebel enables users to describe classpath and ServletContext resource locations using a rebel.xml file. Archives listed in the configuration file are automatically extracted into temporary directories. Our other product, LiveRebel detects the deployed applications both in exploded and packaged forms, and sends the application archives to the LiveRebel Command Center. The exploded deployments need to be compressed before any sending can happen.

We spent some time looking at different libraries out there, but couldn’t find a good API that would fit our needs. So we started using the Java SE API instead. Soon we abstracted most of the use cases into our own ZIP API that we named zt-zip, and hosted on GitHub. After a year of using this, we thought that we could kill two stones with one bird: release something handy for other developers out there to use, and also make everything easier to manage and release as an open source project.

Main Features

We needed a library to operate with Java archives such as JAR, WAR and EAR files, in general they are plain old ZIP archives. The main features were:

  • pack and unpack directories recursively
  • iterate through ZIP entries

In addition the API had to:

  • use existing APIs as much as possible
  • be simple to use
  • be effective to use – no traversing an entire ZIP file if only a single entry is needed
  • be safe to use – not enabling users to leave streams open and keep files locked

What about alternatives?

We found the following existing APIs:

  • java.util.zip package enables to manage ZIP file entries one-by-one in a low-level fashion. It’s all stream-based and there are no ready-to-use methods for compressing or uncompressing directories.
  • Apache Commons Compress is a low-level API like java.util.zip but for other compression formats like tar, gzip, bzip2 etc.
  • Chilkat Java Zip Library is another low-level API but with extensions, e.g. making ZIP files executable. The API has tons of different methods. It’s still a low-level API, as the user must take care of closing the ZIP files and streams, and instead of using Java exceptions, the user must manually check for errors. This makes the API very easy to misuse.

Like I mentioned earlier, we could not find an existing library to fit our needs. So we created our own based on the java.util.zip package.

Quick Example

Here’s how a ZIP file is usually created in Java:

File dir = new File("demo");
ZipOutputStream out = new ZipOutputStream(new FileOutputStream("demo.zip"));
try {
  File[] files = dir.listFiles();
  for (int i = 0; i < files.length; i++) {
    File file = files[i];
    ZipEntry entry = new ZipEntry(file.getName());
    entry.setSize(file.length());
    entry.setTime(file.lastModified());
    out.putNextEntry(entry);
    FileInputStream in = new FileInputStream(file);
    try {
      IOUtils.copy(in, out);
    } finally {
      IOUtils.closeQuietly(in);
    }
    out.closeEntry();
  }
} finally {
  IOUtils.closeQuietly(out);
}

We had to open and close a ZipOutputStream, iterate through a directory and construct the ZipEntry objects. As you see, it’s easy to accidentally leave streams open. What we can do using zt-zip is just a single method call:

ZipUtil.pack(new File("demo"), new File("demo.zip"));

Conclusions

Developing zt-zip has been a success as we use it widely in many projects, including our own tests. The best features of the library are:

  • It has both basic and some advanced features.
  • It is simple to use and it guarantees that no streams are left open by accident.
  • It is efficient when only single entries are extracted from ZIP files.

So how would you use it? Let us know what you think at support@zeroturnaround.com, or in the comments section below. The library is available at our Github repository.

Rein Raudjärv

Rein Raudjärv is a Software Architect at ZeroTurnaround. Rein has developed both JRebel and LiveRebel. In addition he has created internal frameworks for testing these products. He has also been involved in teaching several programming subjects such as Java Fundamentals. Rein is also into photography shooting the cool ZT events.

More Posts

  • OlegYch

    Have you considered Truezip library?

  • http://twitter.com/reinra Rein

    Nope, did not evaluate it. I took a look and I can tell that the main difference is memory consumption. TrueZIP seems to hold the archive file system meta data in heap whereas zt-zip is stream-based so it doesn’t care about the heap size. Our library is also not as generic as TrueZIP. Instead we have methods for common use cases which are simple and safe to use – no stream closing is required by the user.

  • OlegYch

    That’s nice, thanks for sharing.

  • Yonatan Graber

    I took a brief peek in the code, and I asked myself if you’ve heard about lombok-project.
    All those try {} finally { closeQuietly()} blocks can be removed, when using Cleanup annotation over the required resource, and the rethrow() method is useless, as you have the cool SneakyThrow annotation.
    You should really look into it. And if you already know about it, and still decided not to use it, I’d be glad to know what were your concerns. 

  • http://www.zeroturnaround.com/ Toomas Römer

    I’ve heard about it but I’ve never tried it. Are you using it for  most of your projects?

  • Yonatan Graber

    We’ve been using it for over two years in several production systems (mostly in the web-application domain). I haven’t wrote public int getFoo(){ return foo; } for very long time.

  • Matteo Luigi Riso

    Looks like a great ZIP library. I’ll try it for my porting of ZipGenius to Android :) Keep up the good work!

  • http://www.zeroturnaround.com/ Toomas Römer

    Awesome, any feedback appreciated. Ping us if it works on Android, we haven’t ran any tests on it.

  • Matteo Luigi Riso

    I’ll start working as soon as Amazon sends the new CPU, Motherboard and RAM I bought – my desktop PC died on Monday and developing on an Atom netbook is really frustrating…
    I need to know some further detail:
    - Does it support Zip64?
    - Does it support Zip encryption (old password-based and new AES)?
    - Does it support Unicode?

    And a wish in the end: zt-zip looks great and I’m eagerly waiting to work with it (I’m replacing zip4j which seems to have some problem when extracting files from an APK, even though these are ZIP files); it would be really nice to have a similar wrapper for 7-zip compression.

  • Matteo Luigi Riso

    Great News! I’m running zt-zip within my app on my Galaxy S and my Galaxy Note 10.1.
    So, the response is: YES, zt-zip can compile in Eclipse and run in Android.

    Here’s what I did:
    1) I created a library with the source code from github and added to my app;
    2) I downloaded commons.io JAR and added to the new library classpath;
    3) I got rid of every call to Logger and LoggerFactory: I just commented out those lines, for now. I will convert them to the basic Log system for debug purposes;
    4) I copied the example code from github and pasted in my app;
    5) WIN!

    I’m able to decompress a whole archive and to list all of its entries, for now. I’m almost sure that other features will work as well. We’ll see later.

    I don’t understand if is available a method to get some sort of progress monitor while compressing or extracting archives. Maybe I’ll find a workaround.

    I will tune up the library and, if you want, I can give it to you in order to share it with others.

  • Rein Raudjärv

    zt-zip is basically a bunch of helper methods around java.util.zip classes. Currently it doesn’t suport other file formats. It seems that java.util.zip doesn’t support Unicode either (people use Commons Compress for it). I added new feature requests: https://github.com/zeroturnaround/zt-zip/issues

  • Rein Raudjärv

    Great!
    Maven would automatically download the dependencies and build your project. If you change library code it’s hard to replace it with a new version. See SLF4J manual how to configure logging: http://www.slf4j.org/manual.html – you can use NOP logger if you want to disable logging.
    Currently we don’t support a progress monitor. Workaround would be to check the number of entries first and use a NameMapper to get an event per each entry. This would only reflect the number of unpacked entries not their size.

  • JAX Innovation Awards | Most Innovative Java Technology
  • 19th Annual Jolt Productivity Award
  • 2011 Duke's Choice Award
  • EAS Innovator 2011 Competition Winner
  • 2012 Eclipse Community | New Product Showcase Winner
  • 2012 SD Times 100
  • ITL | Breakthrough of the Year