|
|
Input and Output Streams |
Let's rewrite the example from Writing Your Own Filtered Streams so that it works onRandomAccessFiles. BecauseRandomAccessFileimplements theDataInputand
DataOutputinterfaces, a side benefit is that the filtered stream will also work with other
DataInputandDataOutputstreams including some sequential access streams such asDataInputStreamandDataOutputStream.The
CheckedIOTestexample from Writing Your Own Filtered Streams implements two filtered streams,CheckedInputStreamandCheckedOutputStream, that compute a checksum as data is read from or written to the stream.In the new example,
CheckedDataOutputis a re-write ofCheckedOutputStream--it computes a checksum for data writen to the stream--but it operates onDataOutputobjects instead ofOutputStreamobjects. Similarly,CheckedDataInputmodifiesCheckedInputStreamso that it now works onDataInputobjects instead ofInputStreamobjects.
CheckedDataOutputvs.CheckedOutputStreamLet's look at howCheckedDataOutputdiffers fromCheckedOutputStream.The first difference between
CheckedDataOutputandCheckedOutputStreamis thatCheckedDataOutputdoes not extendFilterOutputStream. Instead, it implements theDataOutputinterface.public class CheckedDataOutput implements DataOutput
Note: In the interest of keeping the example simple, theCheckedDataOutputclass actually provided in this lesson is not declared to implementDataOutput, because theDataOutputinterface specifies so many methods. However, theCheckedDataOutputclass as provided in the example does implement several ofDataOutput's methods to illustrate how it should work.
Next,
CheckedDataOutputdeclares a private variable to hold aDataOutputobject.This is the object to which data will be written.private DataOutput out;The constructor for
CheckedDataOutputis different fromCheckedOutputStream's constructor:CheckedDataOutputis created on aDataOutputobject rather than on anOutputStream.This constructor does not callpublic CheckedDataOutput(DataOutput out, Checksum cksum) { this.cksum = cksum; this.out = out; }super(out)like theCheckedOutputStreamconstructor did. This is becauseCheckedDataOutputextends fromObjectrather than a stream class.Those are the only modifications made to
CheckedOutputStreamto create a filter that works onDataOutputobjects.
CheckedDataInputvs.CheckedInputStreamCheckedDataInputrequires the same changes asCheckedDataOuput:In addition to these changes, the
CheckedDataInputdoes not derive fromFilterInputStreambut implements theDataInputinterface instead.
Note: In the interest of keeping the example simple, theCheckedDataInputclass actually provided in this lesson is not declared to implementDataInput, because theDataInputinterface specifies so many methods. However, theCheckedDataInputclass as provided in the example does implement several ofDataInput's methods to illustrate how it should work.
CheckedDataInputdeclares a private variable to hold aDataInputobject which it wraps.- The constructor for
CheckedDataInputrequires aDataInputobject rather than anInputStream.readmethods are changed as well.CheckedInputStreamfrom the original example implements tworeadmethods, one for reading a single byte and one for reading a byte array. TheDataInputinterface has methods that implement the same functionality, but they have different names and different method signatures. Thus thereadmethods in theCheckedDataInputclass 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 (DataInputStreamandDataOutputStreamobjects), and CheckedRAFTest, which runs the filters on random access files (RandomAccessFilesobjects).These two main programs differ only in the type of object they open the checksum filters on.
CheckedDITestcreates aDataInputStreamand aDataOutputStreamand 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);CheckedRAFTestcreates 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
![]()
Input and Output Streams