Home : Course Map : Chapter 9 : Java : Supplements :
ZIP/GZIP Compression and Decompression
JavaTech
Course Map
Chapter 9

Introduction
Overview
Streams
Wrappers,Buffers
Console I/O
  Text Output 
     Demo 1

  Formatter/printf()
     Demo 2

  Tex 2t Input
     Demo 3

  Scanner
     
Demo 4
File Class
  File I/O
  File Output-Text
     Demo 5

  Formatter to File
     Demo 6

  File Input - Text
    Demo 7

  Scanner - Files
     Demo 8

  File I/O - Binary
     Demo 9
   Demo 10
File Chooser Dialog
  Demo 11

Character Codes
  Demo 12
   Demo13
Object I/O
Types to Bytes
Stream Filters
Other I/O Topics
Exercises

    Supplements
Character I/O
  Demo 1   Demo 2
Random Access
  Demo 3
ZIP/GZIP Streams
  Demo 4
Piped Streams
  Demo 5
NIO Framework
More NIO
  Demo 6

     About JavaTech
     Codes List
     Exercises
     Feedback
     References
     Resources
     Tips
     Topic Index
     Course Guide
     What's New

The package java.util.zip provides several tools for compressing and decompressing files. The approach is to use I/O streams. That is, a file to be compressed is read in via an input stream and then sent to an output stream that is wrapped with a stream filter class that compresses the data before it is passed to the destination, which would typically be a disk file. (Note that we will occasionally refer to a compressed output file as an archive.)

Conversely, a file input stream from a compressed file, or an archive file that holds several compressed files, is wrapped with a stream filter that decompresses the data in the stream as it is read.

In Chapter 5 we discussed the JAR (Java Archive) files, which uses the ZIP compression techniques. Classes in java.util.zip allow you to explicitly execute compression / decompression via the ZIP algorithms. It also provides classes for GZIP compression / decompression. We will present here a demonstration program that includes both ZIP and GZIP capabilities.

Note that the java.util.zip package also provides classes for ZLIB compression / decompression and for "computing the CRC-32 and Adler-32 checksums of arbitrary input streams." See the references for information on these tools.

ZIP/GZIP Utility Class

The program ZipGzipper.java shown below contains four static methods:

  • int zipFile (File file_input, File dir_output)
  • int gzipFile (File file_input, File dir_output)
  • int unzipFile (File file_input, File dir_output)
  • int gunzipFile (File file_input, File dir_output)

The zipFile() method compresses the input file (from the file_input argument) and sends the compressed .zip file to the directory specified by the dir_output argument.

The method begins by creating a File object for the output file, whose name is the same as that of the input file except with ".zip" appended to it.

    File zip_output = new File (dir_output, file_input.getName () + ".zip");

The output file object is then wrapped with a FileOutputStream, which in turn is wrapped with a BufferedOutputStream. Finally, the buffered stream is wrapped with ZipOutputStream, which will carry out the compression on the data as it is written to the output file.

    ZipOutputStream zip_out_stream;
    try {
      FileOutputStream out = new FileOutputStream (zip_output);
      zip_out_stream = new ZipOutputStream (new BufferedOutputStream (out));
    }
    catch (IOException e) {
      return STATUS_OUT_FAIL;
    }

The method no sets up to read the input and send the data to the output file. A buffer array is used for the reading and writing of the data.

    byte[] input_buffer = new byte[BUF_SIZE];
    int len = 0;

To ZIP a file, a ZipEntry object that describes the incoming file is first sent to the archive. Here we only use it to enter the name of the compressed file. A buffered input stream to the file to be compressed is created and then the file is read with the buffered array and each buffer written to the output stream, which will compress the data on its way to the archive file.

    try {
      // Use the file name for the ZipEntry name.
      ZipEntry zip_entry = new ZipEntry (file_input.getName ());
      zip_out_stream.putNextEntry (zip_entry);

      // Create a buffered input stream from the file stream.
      FileInputStream in = new FileInputStream (file_input);
      BufferedInputStream source = new BufferedInputStream (in, BUF_SIZE);

      // Now read in the date from the file and write via the zip stream
      // which will compress the data before writing it to the archive
      // output.
      while ((len = source.read (input_buffer, 0, BUF_SIZE)) != -1)
        zip_out_stream.write (input_buffer, 0, len);
      in.close ();
    }
    catch (IOException e) {
      return STATUS_ZIP_FAIL;
    }

    // Close up the output file
    try {
      zip_out_stream.close ();
    }
    catch (IOException e) {}

The method returns an integer to indicate the status of the process.

To decompress a ZIP file, the unzipFile() method is provided. It begins by creating a buffered stream to the archive file and wrapping it with a ZipInputStream object. When data is read from the stream, this filter wrapper will decompress the data as it passed through.

    ZipInputStream zip_in_stream;
    try {
      FileInputStream in = new FileInputStream (file_input);
      BufferedInputStream source = new BufferedInputStream (in);
      zip_in_stream = new ZipInputStream (source);
    }
    catch (IOException e) {
      return STATUS_IN_FAIL;
    }

As before, we use a buffere array for the reading and writing of the data.

    // Need a buffer for reading from the input file.
    byte[] input_buffer = new byte[BUF_SIZE];
    int len = 0;

The ZipEntry for a compressed file in the archive is first read and used to find the name of the file. Then a buffered stream to the output file is created. This is followed by reading the data from the stream from the archive and writing it to the output stream.

    // Loop through the entries in the ZIP archive and read
    // each compressed file.
    do {
      try {
        // Need to read the ZipEntry for each file in the archive
        ZipEntry zip_entry = zip_in_stream.getNextEntry ();
        if (zip_entry == null) break;

        // Use the ZipEntry name as that of the compressed file.
        File output_file = new File (dir_output, zip_entry.getName());

        // Create a buffered output stream.
        FileOutputStream out = new FileOutputStream(output_file);
        BufferedOutputStream destination =
          new BufferedOutputStream (out, BUF_SIZE);

        // Reading from the zip input stream will decompress the data
        // which is then written to the output file.
        while ((len = zip_in_stream.read (input_buffer, 0, BUF_SIZE)) != -1)
          destination.write (input_buffer, 0, len);
        destination.flush (); // Insure all the data is output
        out.close ();
      }
      catch (IOException e) {
        return STATUS_GUNZIP_FAIL;
      }
    } while (true);// Continue reading files from the archive

    try {
      zip_in_stream.close ();
    }
    catch (IOException e) {}


    return STATUS_OK;

Note that the ZipFile class in java.util.zip package can also be used for reading files back from a ZIP archive. See the Sun tutorial for an example program with ZipFile.

The gzipFile() and gunszipFile() methods follows similar procedures but use the corresponding GZIP stream classes.

See the application program on the following page for a demonstration of ZipGzipper.

ZipGzipper.java

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

/**
  * Utility class with methods to zip/unzip and gzip/gunzip files.
 **/
public class ZipGzipper {

  public static final int BUF_SIZE = 8192;

  public static final int STATUS_OK          = 0;
  public static final int STATUS_OUT_FAIL    = 1; // No output stream.
  public static final int STATUS_ZIP_FAIL    = 2; // No zipped file
  public static final int STATUS_GZIP_FAIL   = 3; // No gzipped file
  public static final int STATUS_IN_FAIL     = 4; // No input stream.
  public static final int STATUS_UNZIP_FAIL  = 5; // No decompressed zip file
  public static final int STATUS_GUNZIP_FAIL = 6; // No decompressed gzip file

  private static String fMessages [] = {
    "Operation succeeded",
    "Failed to create output stream",
    "Failed to create zipped file",
    "Failed to create gzipped file",
    "Failed to open input stream",
    "Failed to decompress zip file",
    "Failed to decompress gzip file"
  };

  /** Return a brief message for each status number. **/
  public static String getStatusMessage (int msg_number) {
    return fMessages [msg_number];
  }

  /**
    * Zip the input file and send the zip archive to the output directory.
    * This method only packs one file into the archive.
   **/
  public static int zipFile (File file_input, File dir_output) {

    // Create the output zip archive from the name of the input file
    // and the output directory. Add the ".zip" file type at the end.
    File zip_output = new File (dir_output, file_input.getName () + ".zip");

    // Create a buffered zip output stream to the archive.
    ZipOutputStream zip_out_stream;
    try {
      FileOutputStream out = new FileOutputStream (zip_output);
      zip_out_stream = new ZipOutputStream (new BufferedOutputStream (out));
    }
    catch (IOException e) {
      return STATUS_OUT_FAIL;
    }

    // Now compress the file using the ZIP output stream.
    // Need to use a buffer to read the file.
    byte[] input_buffer = new byte[BUF_SIZE];
    int len = 0;
    try {
      // Use the file name for the ZipEntry name.
      ZipEntry zip_entry = new ZipEntry (file_input.getName ());
      zip_out_stream.putNextEntry (zip_entry);

      // Create a buffered input stream from the file stream.
      FileInputStream in = new FileInputStream (file_input);
      BufferedInputStream source = new BufferedInputStream (in, BUF_SIZE);

      // Now read in the date from the file and write via the zip stream
      // which will compress the data before writing it to the archive
      // output.
      while ((len = source.read (input_buffer, 0, BUF_SIZE)) != -1)
        zip_out_stream.write (input_buffer, 0, len);
      in.close ();
    }
    catch (IOException e) {
      return STATUS_ZIP_FAIL;
    }

    // Close up the output file
    try {
      zip_out_stream.close ();
    }
    catch (IOException e) {}

    return STATUS_OK;

  } // zipFile


  /**
    *  Gzip the input file to an archive with the same name except for
    *  ".gz" appended to it. The archive will be in the chosen output
    *  directory.
   **/
  public static int gzipFile (File file_input, File dir_output) {

    // Create the output gzip archive from the name of the input file
    // and the output directory. Add the ".gz" file type at the end.
    File gzip_output = new File (dir_output, file_input.getName () + ".gz");

    // Create a buffered gzip output stream to the archive.
    GZIPOutputStream gzip_out_stream;
    try {
      FileOutputStream out = new FileOutputStream (gzip_output);
      gzip_out_stream =
        new GZIPOutputStream (new BufferedOutputStream (out));
    }
    catch (IOException e) {
      return STATUS_OUT_FAIL;
    }

    // Now compress the file using the GZIP output stream.
    // Need to use a buffer to read the file.
    byte[] input_buffer = new byte[BUF_SIZE];
    int len = 0;
    try {

      // Create a buffered stream from the input file.
      FileInputStream in = new FileInputStream (file_input);
      BufferedInputStream source = new BufferedInputStream (in, BUF_SIZE);

      // Read from the input stream and write to the gzip output stream
      // which will compress the output before writing to the output file.
      while ((len = source.read (input_buffer, 0, BUF_SIZE)) != -1)
        gzip_out_stream.write (input_buffer, 0, len);
      in.close ();
    }
    catch (IOException e) {
      return STATUS_GZIP_FAIL;
    }

    // Close up the output file
    try {
      gzip_out_stream.close ();
    }
    catch (IOException e) {}

    return STATUS_OK;
  } // gzipFile


  /**
    *  Unzip the files from a zip archive into the given output directory.
    *  It is assumed the archive file ends in ".zip".
   **/
  public static int unzipFile (File file_input, File dir_output) {

    // Create a buffered zip stream to the archive file input.
    ZipInputStream zip_in_stream;
    try {
      FileInputStream in = new FileInputStream (file_input);
      BufferedInputStream source = new BufferedInputStream (in);
      zip_in_stream = new ZipInputStream (source);
    }
    catch (IOException e) {
      return STATUS_IN_FAIL;
    }

    // Need a buffer for reading from the input file.
    byte[] input_buffer = new byte[BUF_SIZE];
    int len = 0;

    // Loop through the entries in the ZIP archive and read
    // each compressed file.
    do {
      try {
        // Need to read the ZipEntry for each file in the archive
        ZipEntry zip_entry = zip_in_stream.getNextEntry ();
        if (zip_entry == null) break;

        // Use the ZipEntry name as that of the compressed file.
        File output_file = new File (dir_output, zip_entry.getName ());

        // Create a buffered output stream.
        FileOutputStream out = new FileOutputStream (output_file);
        BufferedOutputStream destination =
          new BufferedOutputStream (out, BUF_SIZE);

        // Reading from the zip input stream will decompress the data
        // which is then written to the output file.
        while ((len = zip_in_stream.read (input_buffer, 0, BUF_SIZE)) != -1)
          destination.write (input_buffer, 0, len);
        destination.flush (); // Insure all the data is output
        out.close ();
      }
      catch (IOException e) {
        return STATUS_GUNZIP_FAIL;
      }
    } while (true);// Continue reading files from the archive

    try {
      zip_in_stream.close ();
    }
    catch (IOException e) {}


    return STATUS_OK;

  } // unzipFile


  /**
    * Gunzip the input archive. Send the output to the directory specified
    * by dir_output. Assumes that the input file name ends with ".gz"
   **/
  public static int gunzipFile (File file_input, File dir_output) {

    // Create a buffered gzip input stream to the archive file.
    GZIPInputStream gzip_in_stream;
    try {
      FileInputStream in = new FileInputStream(file_input);
      BufferedInputStream source = new BufferedInputStream (in);
      gzip_in_stream = new GZIPInputStream(source);
    }
    catch (IOException e) {
      return STATUS_IN_FAIL;
    }

    // Use the name of the archive for the output file name but
    // with ".gz" stripped off.
    String file_input_name = file_input.getName ();
    String file_output_name =  
      file_input_name.substring (0, file_input_name.length () - 3);

    // Create the decompressed output file.
    File output_file = new File (dir_output, file_output_name);

    // Decompress the gzipped file by reading it via
    // the GZIP input stream. Will need a buffer.
    byte[] input_buffer = new byte[BUF_SIZE];
    int len = 0;
    try {
      // Create a buffered output stream to the file.
      FileOutputStream out = new FileOutputStream(output_file);
      BufferedOutputStream destination =
        new BufferedOutputStream (out, BUF_SIZE);

      // Now read from the gzip stream, which will decompress the data,
      // and write to the output stream.
      while ((len = gzip_in_stream.read (input_buffer, 0, BUF_SIZE)) != -1)
        destination.write (input_buffer, 0, len);
      destination.flush (); // Insure that all data is written to the output.
      out.close ();
    }
    catch (IOException e) {
      return STATUS_GUNZIP_FAIL;
    }

    try {
      gzip_in_stream.close ();
    }
    catch (IOException e) {}

    return STATUS_OK;

  } // gunzipFile

} // ZipGzipper

 

References & Web Resources

 

Most recent update: July 7, 2005

              Tech
Histogram I/O
Hist I/O - Get/Set
  Demo 1
Hist I/O - Objects
  Demo 2
HistogramStream
  Demo 3
Filtering Data
  Demo 4
Exercises

           Physics
Physics Model
Simulation Design
Physics Simulator
  Demo 1
Experiment Design
Experiment Sim.
  Demo 2
Analysis
Expt. + Analysis
  Demo 3
Exercises

  Part I Part II Part III
Java Core 1  2  3  4  5  6  7  8  9  10  11  12 13 14 15 16 17
18 19 20
21
22 23 24
Supplements

1  2  3  4  5  6  7  8  9  10  11  12

Tech 1  2  3  4  5  6  7  8  9  10  11  12
Physics 1  2  3  4  5  6  7  8  9  10  11  12

Java is a trademark of Sun Microsystems, Inc.