Start of Tutorial > Start of Trail > Start of Lesson |
Search
Feedback Form |
Following are the steps to take when you are writing your own filtered input and output streams:This section shows you how to implement your own filter streams, presenting an example that implements a matched pair of filter input and output streams.
- Create a subclass of
FilterInputStream
andFilterOutputStream
. Input and output streams often come in pairs, so it's likely that you will need to create both input and output versions of your filter stream.- Override the
read
andwrite
methods, if you need to.- Provide any new methods.
- Make sure that the input and output streams work together.
Both the input and the output streams use a checksum class to compute a checksum on the data written to or read from the stream. The checksum is used to determine whether the data read by the input stream matches that written by the output stream.
Four classes and one interface make up this example program:
Except for
- The filtered input and output stream subclasses:
CheckedOutputStream
andCheckedInputStream
- The
Checksum
interface and theAdler32
class, which compute a checksum for the streams- The
CheckedIODemo
class to define themain
method for the programCheckedIODemo
, the classes in this example are based on classes, which are now members of thejava.util.zip
package, written by David Connelly.
CheckedOutputStream
ClassTheCheckedOutputStream
class, a subclass ofFilterOutputStream
, computes a checksum on data as it is being written to the stream. When creating aCheckedOutputStream
, you must use its only constructor:This constructor takes anpublic CheckedOutputStream(OutputStream out, Checksum cksum) { super(out); this.cksum = cksum; }OutputStream
argument and aChecksum
argument. TheOutputStream
argument is the output stream that thisCheckedOutputStream
should filter. TheChecksum
argument is an object that can compute a checksum.CheckedOutputStream
initializes itself by calling its superclass constructor and initializing a private variable,cksum
, with theChecksum
object. TheCheckedOutputStream
usescksum
to update the checksum each time data is written to the stream.
CheckedOutputStream
needs to overrideFilterOutputStream
'swrite
methods so that each time thewrite
method is called, the checksum is updated.FilterOutputStream
defines three versions of thewrite
method.CheckedOutputStream
overrides all three of these methods with the following code:The implementations of these threepublic void write(int b) throws IOException { out.write(b); cksum.update(b); } public void write(byte[] b) throws IOException { out.write(b, 0, b.length); cksum.update(b, 0, b.length); } public void write(byte[] b, int off, int len) throws IOException { out.write(b, off, len); cksum.update(b, off, len); }write
methods are straightforward: Write the data to the output stream that this filtered stream is attached to, and then update the checksum.
CheckedInputStream
ClassThe classCheckedInputStream
is similar to theCheckedOutputStream
class. A subclass ofFilterInputStream
, it computes a checksum on data as it is read from the stream. When creating aCheckedInputStream
, you must use its only constructor:This constructor is similar topublic CheckedInputStream(InputStream in, Checksum cksum) { super(in); this.cksum = cksum; }CheckedOutputStream
's.Just as
CheckedOutputStream
needed to overrideFilterOutputStream
'swrite
methods,CheckedInputStream
must overrideFilterInputStream
'sread
methods so that each time theread
method is called, the checksum is updated. As withFilterOutputStream
,FilterInputStream
defines three versions of theread
method.CheckedInputStream
overrides all of them by using the following code:The implementations of these threepublic int read() throws IOException { int b = in.read(); if (b != -1) { cksum.update(b); } return b; } public int read(byte[] b) throws IOException { int len; len = in.read(b, 0, b.length); if (len != -1) { cksum.update(b, 0, b.length); } return len; } public int read(byte[] b, int off, int len) throws IOException { len = in.read(b, off, len); if (len != -1) { cksum.update(b, off, len); } return len; }read
methods are straightforward: Read the data from the input stream that this filtered stream is attached to, then if any data was actually read, update the checksum.
Checksum
Interface and the Adler32
ClassTheChecksum
interface defines four methods for checksum objects to implement. These methods reset, update, and return the checksum value. You could write aChecksum
class that computes a specific type of checksum such as the CRC-32 checksum. Note that inherent in the checksum is the notion of state. The checksum object doesn't just compute a checksum in one pass. Rather, the checksum is updated each time information is read from or written to the stream for which this object computes a checksum. If you want to reuse a checksum object, you must reset it.For this example, we implemented the checksum
Adler32
, which is almost as reliable as a CRC-32 checksum but can be computed more quickly.
The last class in the example,CheckedIODemo
, contains themain
method for the program:Theimport java.io.*; public class CheckedIODemo { public static void main(String[] args) throws IOException { Adler32 inChecker = new Adler32(); Adler32 outChecker = new Adler32(); CheckedInputStream in = null; CheckedOutputStream out = null; try { in = new CheckedInputStream( new FileInputStream("farrago.txt"), inChecker); out = new CheckedOutputStream( new FileOutputStream("outagain.txt"), outChecker); } catch (FileNotFoundException e) { System.err.println("CheckedIODemo: " + e); System.exit(-1); } catch (IOException e) { System.err.println("CheckedIODemo: " + e); System.exit(-1); } int c; while ((c = in.read()) != -1) out.write(c); System.out.println("Input stream check sum: " + inChecker.getValue()); System.out.println("Output stream check sum: " + outChecker.getValue()); in.close(); out.close(); } }main
method creates twoAdler32
checksum objects, one each for aCheckedOutputStream
and aCheckedInputStream
. This example requires two checksum objects because the checksum objects are updated during calls toread
andwrite
and those calls are occurring concurrently.Next,
main
opens aCheckedInputStream
on a small text file,farrago.txt
, and aCheckedOutputStream
on an output file namedoutagain.txt
, which doesn't exist until you run the program for the first time.The
main
method reads the text from theCheckedInputStream
and simply copies it to theCheckedOutputStream
. Theread
andwrite
methods use theAdler32
checksum objects to compute a checksum during reading and writing. After the input file has been completely read and the output file has been completely written, the program prints out the checksum for both the input and output streams (which should match) and then closes them both.When you run
CheckedIODemo
, you should see this output:Input stream check sum: 736868089 Output stream check sum: 736868089
Start of Tutorial > Start of Trail > Start of Lesson |
Search
Feedback Form |
Copyright 1995-2005 Sun Microsystems, Inc. All rights reserved.