|
Creating a Bit Data Format
It's important to understand that BitInputStream and BitOutputStream don't use a special formatthey use the bits contained in traditional Java streams, except that they deal with the data one bit at a time.
There is a flaw to this approach. File systems themselves deal with data in terms of bytes. Files must contain whole bytesit's not possible to have a file that contains a partial byte. You can, of course, write a partial byte by padding the byte with zeros and writing the entire byte. The problem with this approach is that when you read the file in again, you can't distinguish between the actual data bytes and the padding. Practically speaking, this means that you can write a certain number of bits to a filebut when you read the file back in, it may contain more bits than you originally wrote out.
And it's not just files: most streams are connected, in the end, to some facility that deals with bytes, not with individual bits.
The essence of the problem is that a bit stream (a BitInputStream or BitOutputStream) is slightly more general than a byte stream (an InputStream or OutputStream). A sequence of bits can be any length; a sequence of bytes has a length, in bits, that is an even multiple of eight.
It's possible to create a special file format that could store extra information, such as the number of padding bits, which would allow perfect reconstruction of a byte stream. However, that's not the primary goal. The primary goal is to be able to view any data sourcesuch as a fileas a stream of bits.
Doing Without Stream Inheritance
If you look at the source code in Listing 1 and Listing 2, you'll find that neither BitInputStream nor BitOutputStream are subclasses of InputStream and OutputStream. Again, that underscores the basic difference between bit streams and byte streams. Most of the methods of InputStream and OutputStream would be meaningless, or at least awkward, as part of a BitInputStream or BitOutputStream implementation.
However, the methods that the BitInputStream and BitOutputStream classes have are analogous to the methods in the traditional stream classes. As you saw in the usage examples, these classes take streams in their constructors, much like traditional stream filters:
BitOutputStream bout = new BitOutputStream( out );
Where traditional stream classes have read() or write() methods, the BitInputStream and BitOutputStream classes have readBit() and writeBit() methods.
bout.writeBit( 1 );
And, like traditional stream methods, the classes have close() methods:
bout.close();
Because they aren't subclasses of InputStream and OutputStream, the bit streams classes can't be used as simple replacements. But that's fineit doesn't really make sense to try to use bit streams in places where you need byte streams.
|