Reading and Writing |
Let's rewrite the example from Writing Your Own Filtered Streams so that it works onRandomAccessFiles
. BecauseRandomAccessFile
implements theDataInput
andDataOutput
interfaces, a side benefit is that the filtered stream will also work with otherDataInput
andDataOutput
streams including some sequential access streams such asDataInputStream
andDataOutputStream
.The
CheckedIOTest
example from Writing Your Own Filtered Streams implements two filtered streams,CheckedInputStream
andCheckedOutputStream
, that compute a checksum as data is read from or written to the stream.In the new example,
CheckedDataOutput
is a re-write ofCheckedOutputStream
--it computes a checksum for data writen to the stream--but it operates onDataOutput
objects instead ofOutputStream
objects. Similarly,CheckedDataInput
modifiesCheckedInputStream
so that it now works onDataInput
objects instead ofInputStream
objects.
CheckedDataOutput
vs.CheckedOutputStream
Let's look at howCheckedDataOutput
differs fromCheckedOutputStream
.The first difference between
CheckedDataOutput
andCheckedOutputStream
is thatCheckedDataOutput
does not extendFilterOutputStream
. Instead, it implements theDataOutput
interface.public class CheckedDataOutput implements DataOutput
Note: In the interest of keeping the example simple, theCheckedDataOutput
class actually provided in this lesson is not declared to implementDataOutput
, because theDataOutput
interface specifies so many methods. However, theCheckedDataOutput
class as provided in the example does implement several ofDataOutput
's methods to illustrate how it should work.
Next,
CheckedDataOutput
declares a private variable to hold aDataOutput
object.This is the object to which data will be written.private DataOutput out;The constructor for
CheckedDataOutput
is different fromCheckedOutputStream
's constructor:CheckedDataOutput
is created on aDataOutput
object rather than on anOutputStream
.This constructor does not callpublic CheckedDataOutput(DataOutput out, Checksum cksum) { this.cksum = cksum; this.out = out; }super(out)
like theCheckedOutputStream
constructor did. This is becauseCheckedDataOutput
extends fromObject
rather than a stream class.Those are the only modifications made to
CheckedOutputStream
to create a filter that works onDataOutput
objects.
CheckedDataInput
vs.CheckedInputStream
CheckedDataInput
requires the same changes asCheckedDataOuput
:In addition to these changes, the
CheckedDataInput
does not derive fromFilterInputStream
but implements theDataInput
interface instead.
Note: In the interest of keeping the example simple, theCheckedDataInput
class actually provided in this lesson is not declared to implementDataInput
, because theDataInput
interface specifies so many methods. However, theCheckedDataInput
class as provided in the example does implement several ofDataInput
's methods to illustrate how it should work.
CheckedDataInput
declares a private variable to hold aDataInput
object which it wraps.- The constructor for
CheckedDataInput
requires aDataInput
object rather than anInputStream
.read
methods are changed as well.CheckedInputStream
from the original example implements tworead
methods, one for reading a single byte and one for reading a byte array. TheDataInput
interface has methods that implement the same functionality, but they have different names and different method signatures. Thus theread
methods in theCheckedDataInput
class have new names and method signatures:public byte readByte() throws IOException { byte b = in.readByte(); cksum.update(b); return b; } public void readFully(byte[] b) throws IOException { in.readFully(b, 0, b.length); cksum.update(b, 0, b.length); } public void readFully(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
andDataOutputStream
objects), and CheckedRAFTest, which runs the filters on random access files (RandomAccessFiles
objects).These two main programs differ only in the type of object they open the checksum filters on.
CheckedDITest
creates aDataInputStream
and aDataOutputStream
and uses the checksum filter on those, as in the following code:cis = new CheckedDataInput(new DataInputStream( new FileInputStream("farrago.txt")), inChecker); cos = new CheckedDataOutput(new DataOutputStream( new FileOutputStream("outagain.txt")), outChecker);CheckedRAFTest
creates twoRandomAccessFiles
, one for reading and one for writing, and uses the checksum filter on those: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:
Input stream check sum: 736868089 Output stream check sum: 736868089
Reading and Writing