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
|