Zip Meets Java

javaThe ZIP file format has become extremely popular for the distribution and storage of files… The java.util.zip package allows for the programmatic reading and writing of the ZIP and GZIP formats. As you’ll see in this article, the API for reading and writing ZIP files is pretty straightforward to use… In this article, I’ll take you through a Java program that creates of a ZIP file and also walk you through another Java program that unzips the file we created.

The ZIP file format has become extremely popular for the distribution and storage of files. ZIP files allow for compression, making transporting a set of files from one location to another (e.g., across a network) faster. When a person is downloading files via a dial up connection, the size of the file being downloaded can make the difference between sanity and being fitted for a straight jacket. Depending on the source file types being compressed, ZIP files can provide significant space savings. ZIP archives can also maintain the directory structure of files that are compressed, making the ZIP format a formidable file transport mechanism.

The java.util.zip package allows for the programmatic reading and writing of the ZIP and GZIP formats. As you’ll see in this article, the API for reading and writing ZIP files is pretty straightforward to use. Learning how to use the offerings of the java.util.zip package might best be facilitated via example. In this article, I’ll take you through a Java program that creates of a ZIP file and also walk you through another Java program that unzips the file we created.{mospagebreak title=Zipping Things Up with Java} First, let’s ZIP up a set of files. In the code in Listing 1, we first define a set of files to be added to our ZIP file. Notice that we state the location of the files on our hard drive. One of our files is located in a subdirectory. You will see later that the directory structure of our files will be kept within the ZIP file we construct. The ZIP file we are creating is called example.zip and will be stored in the root of the C drive. We also create a buffer to aid us as we write our ZIP file. Note that the buffer size must be big enough to house the files you want added to the ZIP file.

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.zip.Deflater;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

public class ZipCreateExample {

   public static void main(String[] args) {
     System.out.println(“Example of ZIP file creation.”);

     // Specify files to be zipped
     String[] filesToZip = new String[3];
     filesToZip[0] = “firstfile.txt”;
     filesToZip[1] = “secondfile.txt”;
     filesToZip[2] = “tempthirdfile.txt”;

     byte[] buffer = new byte[18024];

     // Specify zip file name
     String zipFileName = “c:example.zip”;

     try {

       ZipOutputStream out =
         new ZipOutputStream(new FileOutputStream(zipFileName));

       // Set the compression ratio
       out.setLevel(Deflater.DEFAULT_COMPRESSION);

       // iterate through the array of files, adding each to the zip file
       for (int i = 0; i < filesToZip.length; i++) {
         System.out.println(i);
         // Associate a file input stream for the current file
         FileInputStream in = new FileInputStream(filesToZip[i]);

         // Add ZIP entry to output stream.
         out.putNextEntry(new ZipEntry(filesToZip[i]));

         // Transfer bytes from the current file to the ZIP file
         //out.write(buffer, 0, in.read(buffer));

         int len;
        while ((len = in.read(buffer)) > 0)
        {
        out.write(buffer, 0, len);
       }



         // Close the current entry
         out.closeEntry();

         // Close the current file input stream
         in.close();

       }
       // Close the ZipOutPutStream
       out.close();
     }
     catch (IllegalArgumentException iae) {
       iae.printStackTrace();
     }
     catch (FileNotFoundException fnfe) {
       fnfe.printStackTrace();
     }
     catch (IOException ioe)
     {
     ioe.printStackTrace();
     }


   }
}


The core of our ZIP file construction is performed in our try-catch clause. First we create a new ZipOutputStream object. On this object, we use the setLevel method to specify the compression ratio we’d like to use when we create our ZIP file. The Deflater object contains static member variables for specifying such compression options as best compression (i.e., BEST_COMPRESSION), best speed (i.e., BEST_SPEED), no compression (i.e., NO_COMPRESSION). In our code, we specify the option of BEST_COMPRESSION.

To add files to our zip file, we iterate through our filesToZip file name array, each time associating a FileInputStream to the file we are currently working with. On all iterations, we also use the putNextEntry method of our ZipOutputStream object, to add the current file to our target Zip file, followed by a writing of the bytes of the current file to the ZipOutputStream. After each file is written, we must use the closeEntry method. Finally, after iterating is complete, we use the close method to close off our ZipOutPutStream, thereby sealing our ZIP file. {mospagebreak title=Unzipping Things with Java} So we can create zip files with Java. Can we extract them? Listing 2 shows an example Java class that can do just that. Let’s cover what’s going on in the class, as it might not be that obvious to the java.util.zip API newcomer.

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
public class ZipUncompressExample
{

   // specify buffer size for extraction
   static final int BUFFER = 2048;

   public static void main(String[] args)
   {
     try
     {
       System.out.println("Example of ZIP file decompression.");

       // Specify file to decompress
       String inFileName = "c:example.zip";
       // Specify destination where file will be unzipped
       String destinationDirectory = "c:temp";

       File sourceZipFile = new File(inFileName);
       File unzipDestinationDirectory = new File(destinationDirectory);

       // Open Zip file for reading
       ZipFile zipFile = new ZipFile(sourceZipFile, ZipFile.OPEN_READ);

       // Create an enumeration of the entries in the zip file
       Enumeration zipFileEntries = zipFile.entries();

       // Process each entry
       while (zipFileEntries.hasMoreElements())
       {
         // grab a zip file entry
         ZipEntry entry = (ZipEntry) zipFileEntries.nextElement();

         String currentEntry = entry.getName();
         System.out.println("Extracting: " + entry);

         File destFile =
           new File(unzipDestinationDirectory, currentEntry);

         // grab file's parent directory structure
         File destinationParent = destFile.getParentFile();

         // create the parent directory structure if needed
         destinationParent.mkdirs();

         // extract file if not a directory
         if (!entry.isDirectory())
         {
           BufferedInputStream is =
             new BufferedInputStream(zipFile.getInputStream(entry));
           int currentByte;
           // establish buffer for writing file
           byte data[] = new byte[BUFFER];

           // write the current file to disk
           FileOutputStream fos = new FileOutputStream(destFile);
           BufferedOutputStream dest =
           new BufferedOutputStream(fos, BUFFER);

           // read and write until last byte is encountered
           while ((currentByte = is.read(data, 0, BUFFER)) != -1)
           {
             dest.write(data, 0, currentByte);
           }
           dest.flush();
           dest.close();
           is.close();
         }
       }
       zipFile.close();
     }
     catch (IOException ioe)
     {
     ioe.printStackTrace();
     }
   }
}

The ZipUncompressExample class unzips a file called example.zip and extracts it to a destination directory called d:temp. We first open the source zip file. From our ZipFile object, we can use the entires() method to obtain an Enumeration which contains ZipEntry objects. These individual ZipEntry objects represent the entries which make up the Zip file.

I then use a while loop to cycle through the entries of our Zip file. As we process each ZipEntry object, we have to check and see if the zip entry in question has the needed housing directory structure in place. If the needed directories are not created, they are established. We use the getParentFile method of the File class to obtain the parent directory structure. If the current zip entry is not a directory (i.e., a file), we write the file to disk in the corresponding housing directory. This process is continued until each entry in the Zip file is processed. {mospagebreak title=Conclusion} In this article, you learned how to use the Java APIs for the reading and writing of ZIP files available in the java.util.zip package. As the ZIP file format is extremely popular and used quite commonly for its advantages of compression and ease of storage, being able to programmatically ZIP and UNZIP files presents a valuable facility to the Java developer. One can do such things as build applications that dynamically create ZIP files on an as needed basis from a specified set of files.

Google+ Comments

Google+ Comments