![]() ![]() ![]() ![]() |
Input and Output Streams |
This page will show you how to write a filters for DataInput and DataOutput objects such that they will work on (some) sequential access files as well as on random access files.The CheckedIOTest example from Writing Your Own Filtered Streams implemented two filtered streams, CheckedInputStream and CheckedOutputStream, that computed a checksum as data was read from or written to the stream.
CheckedDataOutput is based on CheckedOutputStream--it computes a checksum for data writen to the stream--but it operates on DataOutput objects instead of OutputStream objects. Similarly, CheckedDataInput modifies CheckedInputStream so that it now works on DataInput objects instead of InputStream objects.
CheckedDataOutput vs. CheckedOutputStream
Let's look at how CheckedDataOutput differs from CheckedOutputStream.The first difference between CheckedDataOutput and CheckedOutputStream is that CheckedDataOutput does not extend FilterOutputStream but rather implements the DataOutput interface instead.
public class CheckedDataOutput implements DataOutput
Note: In the interest of keeping the example simple, the CheckedDataOutput class actually provided in this lesson is not declared to implement DataOutput. This is because the DataOutput interface specifies so many methods. However, the CheckedDataOutput class as provided in the example does implement several of DataOutput's methods to illustrate how it should work.
Next, CheckedDataOutput declares a private variable to hold a DataOutput object.
This is the object to which data will be written. CheckedDataOutput is said to wrap the DataOutput object--and each of CheckedDataOutput's methods wraps a call to the same method in the DataOutput object while performing the filtering function.private DataOutput out;The constructor for the two classes is different as well. CheckedDataOutput is created on a DataOutput object rather than on an OutputStream.
Notice that this constructor does not callpublic CheckedDataOutput(DataOutput out, Checksum cksum) { this.cksum = cksum; this.out = out; }super(out)
like the CheckedOutputStream constructor did. This is because CheckedDataOutput inherits from Object rather than from a stream.Those are the only modifications made to CheckedOutputStream to create a filter that works on DataOutput objects.
CheckedDataInput vs. CheckedInputStream
CheckedDataInput required the same changes as did CheckedDataOuput:In addition to these changes, the
- CheckedDataInput does not derive from FilterInputStream but implements the DataInput interface instead.
Note: In the interest of keeping the example simple, the CheckedDataInput class actually provided in this lesson is not declared to implement DataInput. This is because the DataInput interface specifies so many methods. However, the CheckedDataInput class as provided in the example does implement several of DataInput's methods to illustrate how it should work.
- CheckedDataInput declares a private variable to hold a DataInput object which it wraps.
- The constructor for CheckedDataInput requires a DataInput object rather than an InputStream.
read()
methods had to be changed as well. CheckedInputStream from the original example implement tworead()
methods, one for reading a single byte and one for reading a byte array. The DataInput interface also has methods for reading a single and for reading a byte array, but they have different names and different method signatures. Thus the new classes rewrote and renamed theread()
methods so that they would operate on a DataInput object:public byte readByte() throws IOException { byte b = in.readByte(); cksum.update(b); return b; } public void read(byte[] b, int off, int len) throws IOException { in.readFully(b, off, len); cksum.update(b, off, len); }The Main Programs
Finally, this example has two main programs to test the new filters: CheckedDITest which runs the filters on sequential access files (DataInputStream and DataOutputStream objects), and CheckedRAFTest which runs the filters on random access files (RandomAccessFiles).These two main programs only differ in the type of object they open the checksum filters on. CheckedDITest creates a DataInputStream and a DataOutputStream and uses the checksum filter on those:
CheckedRAFTest creates two RandomAccessFiles, one for reading and one for writing, and uses the checksum filter on those:cis = new CheckedDataInput(new DataInputStream( new FileInputStream("farrago.txt")), inChecker); cos = new CheckedDataOutput(new DataOutputStream( new FileOutputStream("outagain.txt")), outChecker);cis = new CheckedDataInput(new RandomAccessFile("farrago.txt", "r"), inChecker); cos = new CheckedDataOutput(new RandomAccessFile("outagain.txt", "rw"), outChecker);When you run either of these programs you should see the following output:
Note: These example programs do not close the filters or the RandomAccessFiles when it completes and it should.Input stream check sum: 736868089 Output stream check sum: 736868089See Also
java.io.DataInput
java.io.DataOutput
![]() ![]() ![]() ![]() |
Input and Output Streams |