Java Zip API: How to Create a Zip File Using Java

July 11, 2010 | By Rakhitha | Filed in: Java Stuff, Tech.

This is a follow-up to my earlier post “Java Zip API: How to Read a Zip File Using Java“. This time it’s about how to create a zip file using Java. This is even simpler than reading a zip file.

Following is a very simple example which create a zip file named RaKasUniverse.zip. Inside that zip file we will create a directory named MyDirectory and inside that, we will have a file named MyFile.txt. That text file will contain the text “Java Zip API: How to Create a Zip File Using Java”. In the example we will be using following classes from Java API.

java.util.zip.ZipOutputStream – This is the main class that we will use. It allows you to write zipped data into another Output stream.

java.io.FileOutputStream – ZipOutputStream is only capable of compressing data and sending to another stream. If we want compressed data to end up in a file in hard disk, we need to use a FileOutputStream. Ultimately we will wrap FileOutputStream with ZipOutputStream. And we will only deal with ZipOutputStream.

java.util.zip.ZipEntry – If you remember my post on reading a zip file, a ZipEntry represent a file inside the zip file. When we read the zip file, we actually find and read ZipEntries. When we write a zip file, we are going to create and put zip entries in to a ZipOutputStream.

import java.io.FileOutputStream;
import java.nio.charset.Charset;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

public class CreateZipFile {
	public static void main(String args[])throws Exception
	{
		//Create a new file to store the zipped content
		FileOutputStream fout = new FileOutputStream("RaKasUniverse.zip");

		//Create ZipOutputStream instance for that file by wrapping previously created FileOutputStream.
		//We could have actually done this in one line of code but I have separated it for clarity.
		ZipOutputStream zip = new ZipOutputStream(fout);

		//Now we set the compression level. This step is optional.
		//If we don't set compression levels, default values will be used.
		//I am just setting them so that you know how to do it.
		zip.setMethod(ZipOutputStream.DEFLATED);
		zip.setLevel(9);

		//Now we going to put a file inside our zip file.
		//The file will be named "MyFile.txt"
		//It will be inside the directory "MyDirectory"
		zip.putNextEntry(new ZipEntry("MyDirectory/MyFile.txt"));

		//Now we will write the content for above file
		//In our case the content will be just a string
		String content = "Java Zip API: How to Create a Zip File Using Java";

		//We will simply use write(byte b[]) method in ZipOutputStream to write
		//We will convert string to UTF-8 encoding before writing
		zip.write(content.getBytes(Charset.forName("UTF-8")));

		//Now we are done with writing this zip entry so we close it
		zip.closeEntry();

		//Here we can add more zip entries to our zip file
		//We just need to create and put a zip entry for each zipped file
		//and then write the content and close the entry.

		//After we are done adding all Zip entries we can close the file
		zip.close();

	}
}

In above code in line 10 we are simply create a file named “RaKasUniverse.zip”. And in line 14 we are wrapping it with a ZipOutputStream. Form that point on we will only deal with ZipOutputStream instance. FileOutputstream is only for directing the data in to a file on disk.

In line 19 and 20, we are setting compression method and compression level. Compression method can be either ZipOutputStream.DEFLATED or ZipOutputStream.STORED. Default value is ZipOutputStream.DEFLATED which means compress. If you use ZipOutputStream.STORED files will be stored without being compressed. If you use ZipOutputStream.DEFLATED method, which is the default, you can also set compression level (line 20) using ZipOutputStream.setLevel method. Compression level can be a value between 0 to 9. For more details please look in java documentation for methods “setMethod” and “setLevel“.

Once above initialization is done, it’s a matter of adding individual zip entries, which is quite straight forward. First you create a ZipEntry which represent the path of the new entry within the zip file (in our case “MyDirectory/MyFile.txt”). And then you put it in to ZipOutputStream using method putNextEntry (Please see line 25 in above code). Then we write the data which should go in to the entry, by calling write method on ZipOutputStream, just like you write stuff in to any OutputStream (Line 33) and then we close the ZipEntry by calling closeEntry method (Line 36). In my example I am just writing a text string using UTF-8 character encoding. But you can write pretty much anything you want.

Finally once we are done writing everything, we can call close method on ZipOutputStream to close it just like any other OutputStream.

Go ahead, run the code and check out the zip file it create :). You can also try to modify the code to include more than one file inside the zip file.

Lets build a little bit on top of above example. In above example, even if we write 100s of files in to a single zip file, we are writing only in to a single output stream. Which is a bit different from how we used to work with file streams. Normally we would prefer to open a new stream per file and close it once we are done with it. Even when we read zip files we read a separate stream per ZipEntry. Lets look at a way which allows us to handle a each file that goes in to a Zip file as a separate stream by handing each ZipEntry in a separate stream.

To do this we need to write a new output stream class. Lets call it ZipEntryOutputStream. And its code will look like following. Actual logic for creating and closing the ZipEntry is placed inside the constructor and close method of the stream. Rest of the methods simply call respective methods in ZipOutputStream

package info.RakasUniverse.zip;

import java.io.IOException;
import java.io.OutputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * @author Rakhitha
 * This class allows to wrap each ZipEntry inside it's own OutputStream
 * allowing to make writing a zip file much more simple.
 * Logic is only written inside constructor and close method.
 * Rest of the methods are simply delegating to ZipOutputStream
 */
public class ZipEntryOutputStream extends OutputStream{

	ZipOutputStream zip;
	/**
	 * Simply create the stream by wrapping ZipOutputStream inside it and add a zip entry to
	 *  ZipOutputStream to represent the data written through this stream.
	 *
	 * @param zip - The ZipOutputStream instanced which represent the zip file to which the new entry should be added
	 * @param path - Path of the new zip entry within the zip file
	 * @throws IOException
	 */
	public ZipEntryOutputStream(ZipOutputStream zip, String path)throws IOException
	{
		this.zip = zip;
		zip.putNextEntry(new ZipEntry(path));
	}

	/**
	 * Close the zip entry represented by this stream
	 */
	@Override
	public void close() throws IOException {
		zip.closeEntry();
	}

	/*
	 * All the following methods simply send the call to ZipOutputStream instance
	 *
	 */
	@Override
	public void flush() throws IOException {
		zip.flush();
	}

	@Override
	public void write(byte[] b, int off, int len) throws IOException {
		zip.write(b, off, len);
	}
	@Override
	public void write(byte[] b) throws IOException {
		zip.write(b);
	}
	@Override
	public void write(int b) throws IOException {
		zip.write(b);
	}

}

Using above class make the task of adding stuff in to a zip file much more simple. Because it hide the complexities of creating and closing ZipEntries. Same example I described earlier will look like following when used above class.

import info.RakasUniverse.zip.ZipEntryOutputStream;

import java.io.FileOutputStream;
import java.io.PrintStream;
import java.util.zip.ZipOutputStream;

public class UsingZipEntryOutputStream {
	public static void main(String args[])throws Exception
	{
		//Initial steps of setting up ZipOutputStream is same
		FileOutputStream fout = new FileOutputStream("UsingZipEntryOutputStream.zip");
		ZipOutputStream zip = new ZipOutputStream(fout);
		zip.setMethod(ZipOutputStream.DEFLATED);
		zip.setLevel(9);

		//But now we can use our new stream class and use it with any other stream
		//For example lets use it with a print stream
		PrintStream ps = new PrintStream(new ZipEntryOutputStream(zip,"MyDirectory/MyFile.txt"));
		ps.println("Java Zip API: How to Create a Zip File Using Java");
		ps.println("It's much more simple to write zip file content this way");
		ps.close();

		zip.close();
	}
}

Hope you find this post useful!

/Rakhitha


Tags: , , , , ,

5 comments on “Java Zip API: How to Create a Zip File Using Java

  1. Java vb says:

    Hi theirs not really a great difference between java and vb is their?

  2. Rakhitha says:

    It depends on which VB version that you compare with java. If you compare VB 6 it is different in syntax as well as language features. But if you take VB.Net it is pretty much similar to java in features but different in syntax.

  3. Henrik says:

    Thanks! Exactly what I was looking for!

    // Henrik

  4. website says:

    As a net resource for organizations and technological innovation enthusiasts to follow the latest and greatest advancements in Unified Communications, IP Telephony, Hosted Communications and VoIP.

  5. B says:

    Great Post, Thank you ! 🙂