Apr 12, 2012

Inflating and Deflating


This section explores inflating and deflating in Java code. These terms have the same meaning as compressing and uncompressing. Some of the key points in this section are:
     Ø  DeflaterInputStream and DeflaterOutputStream
     Ø  ZipInputStream and ZipOutputStream
     Ø  ZipFile


Deflater
         Let's move into deflating territory. Deflating writes a compressed representation of bytes to an output stream. Inflating takes those compressed bytes from an input stream, reads them in, and automatically uncompresses them. This process is similar to zipping and unzipping on the fly.
The algorithm of a Deflater is applied to the bytes output to a stream, and the corresponding algorithm of an Inflater is applied to the bytes input from a stream. The default Deflater and Inflater use the ZLIB compression library for compression and decompression. An alternate constructor allows for GZIP and PKZIP compression.


DeflaterOutputStream
         Let's journey into the output stream. You can simply create a DeflaterOutputStream with an output sink. As we write to the DeflaterOutputStream , the bytes are compressed using the Deflater algorithm and only the compressed bytes are sent to the underlying output stream. The default constructor for DeflaterOutputStream uses ZLIB compression with a default-sized buffer. With the other constructors, you can specify a different Deflater and a different-sized buffer. 


InflaterInputStream
         On the receiving side, an InflaterInputStream is implemented. When we construct it, we specify an input source. It uncompresses the bytes from that source as you go along. Once again, you can specify your own Inflater if you use a different compression scheme.
If you decide to use your own Deflater or Inflater instead of the default, then it is up to you to make sure the Inflater and Deflater match and understand each other. 


GZIP input and output stream
         A GZipOutputStream outputs the compressed bytes to the underlying stream in GZIP format. It is derived from the DeflaterOutputStream. The constructor is supplied an OutputStream. Correspondingly, a GZIPInputStream inputs from a source that is in GZIP format. It is derived from InflaterInputStream , and the constructor is supplied an InputStream.
Use GZIPInputStream and GZipOutputStream on a single stream, which could be a file. However, it can be more efficient than a zip stream because it does not require creating a directory of zipped files.

ZipFile: Example code
         Let's look into the ZipFile and ZipEntry classes. These are not actually in the I/O hierarchy but they are good to know about because lots of people have zip files.
The ZipFile class allows us to read a zip file. A zip file consists of two parts: a list of entries of what's been zipped and the data itself. You read the set of entries using entries() and pick out a particular one to unzip. A ZipEntry object represents the file you have selected to uncompress. For that  particular ZipEntry , you can obtain an InputStream using getInputStream() which, when read, returns the uncompressed data. The Java library is kept in a jar file, which is in zip file format. You can use a ZipFile to read a jar file if you want.

Here is the example code:

import java.util.zip.*;
import java.util.*;
import java.io.*;
class ZipFileExample
{
public static void main(String argv[])
{
try
{
ZipFile zf = new ZipFile("test.Zip");
// Enumerate the entries
Enumeration zip_entries = zf.entries();
String last_name = null;
while(zip_entries.hasMoreElements())
{
ZipEntry ze = (ZipEntry) zip_entries.nextElement();
System.out.println("Entry " + ze.getName());
last_name = ze.getName();
}
// Lets unpack the last one as an example
// Its name is in last_name
ZipEntry ze = zf.getEntry(last_name);
if (ze == null)
System.out.println("Cannot find entry");
else
{
BufferedReader r =
new BufferedReader(new InputStreamReader(
zf.getInputStream(ze)));
long size = ze.getSize();
if (size > 0)
{
System.out.println("File is " + size);
String line = r.readLine();
if (line != null)
System.out.println("First line is " + line);
}
r.close();
}
}
catch(IOException e)
{
System.out.println(e);
}
}
}

ZipInputStream
          ZipInputStream is our next stop. You can read a zip file in a stream using this class. You get the first entry in the directory of what has been zipped.You can then read the data for the first entry, which is automatically unzipped. Then you get the next entry and unzip it, and so forth. ZipInputStream extends InflaterInputStream.The methods include getting the next entry from the table and closing off the entry. Closing the entry allows for the next entry to be read without having to finish reading the data for the current entry. The read() method in ZipInputStream will return -1 when the last of the entries is read.

ZipInputStream: Example code
           The code below is an example of unzipping a file. You are going to open test.Zip , which is our zip file. That file is the source of a ZipInputStream. So zis is pointing to test.Zip.The getNextEntry() method initially returns the first entry from the zip file table. A reference to that entry is now available.
If the entry is null, it means that end-of-file has been reached. Reading from the zip file from this point, data that is read corresponds to that entry and is automatically uncompressed. In this case, a DataInputStream has been wrappered and used to read it. The dis object is just going to read from the corresponding place in the zip file and close it. The next entry will open the file and start reading from the zip file again, reading the next entry.

Here is the example code:

import java.util.zip.*;
import java.io.*;
class ZipInputStreamExample
{
public static void main(String argv[])
{
try
{
FileInputStream fis = new FileInputStream("test.Zip");
ZipInputStream zis = new ZipInputStream(fis);
ZipEntry ze;
// Get the first entry
ze = zis.getNextEntry();
if (ze == null)
System.out.println("End entries");
else
{
// Use it as stream or reader
DataInputStream dis = new DataInputStream(zis);
int i = dis.readInt();
System.out.println("File contains " + i);
zis.closeEntry();
}
zis.close();
}
catch(Exception e)
{
System.out.println(e);
}
}

ZipOutputStream
          A ZipInputStream reads a zip-formatted stream; a ZipOutputStream writes zip-formatted streams. This class allows us to create a zip file.ZipOutputStream extends DeflaterOutputStream.One method in ZipOutputStream is putNextEntry() , which puts the next entry into the list of compressed files. You need to create a zip entry for each file you are compressing.
The putNextEntry() method writes an entry and positions the stream for data output. You can start writing the next set of compressed data. Similar to the close() methods in other classes, the closeEntry() method closes a finished entry; you are ready to create the next one.

ZipOutputStream: Example code
          In the code below, an output file is constructed called test.Zip. A ZipOutputStream is then constructed using that file. We want to compresss the file test.txt onto the zip file, so we construct a ZipEntry using that name.
test.txt is going to show up in the directory for the zip file. At this point, anything written to the ZipOutputStream is now data for that entry and is written in compressed form.
A DataOutputStream is wrappered around zos. Then we write an integer, and the entry is closed. At this point, another ZipEntry could now be created and written out. You could use WinZip to  decompress this file or use the preceding example to read the file.

Here is the example code:

import java.util.zip.*;
import java.io.*;
class ZipOutputStreamExample
{
public static void main(String argv[])
{
try
{
FileOutputStream fos = new FileOutputStream("test.Zip");
ZipOutputStream zos = new ZipOutputStream(fos);
ZipEntry ze = new ZipEntry("test.txt");
zos.putNextEntry(ze);
// Use it as output
DataOutputStream dos = new DataOutputStream(zos);
dos.writeInt (1);
zos.closeEntry();
// Put another entry or close it
zos.close();
}
catch(Exception e)
{
System.out.println(e);
}
}
}



0 comments :

Post a Comment