Byte streams are a sequence of bytes used by programs to input and output information. The terms byte stream and octet-stream are both used somewhat synonymously, though octet streams are common among networking terminology.
As one tries to wrap their head around byte streams, the first question is often what’s a byte? A byte is simply a series of 8-bits (1 or 0 values.) The separating factor between a bit stream and byte stream is the decision to interpret the stream in 8-part groups rather than single discrete units.
Bits vs. Bytes
Essentially, a bitstream becomes a byte stream when it’s interpreted as a series of 8-bit sequences rather than a sequence of 1’s and 0’s. If one is in a more formal mood, it can be called an octet-stream. It’s still a bunch of 1’s and 0’s but with the implication that one should interpret the data as an array of 8-bit values.
Can a byte be considered a bitstream? I suppose, technically. The qualifier stream is generally reserved in describing data large enough to exceed common unit notation.
Byte Stream
In the above example, the data can be interpreted as simple 1’s and 0’s amounting to the binary value of 102. However, if this were taken as a smaller segment within an indeterminately-long bitstream—even that interpretation wouldn’t be possible.
If one chooses to interpret the data as a series of 8-bit bytes, many more interpretations based on this minimal structuring are possible. For example, a byte stream could be interpreted in ASCII such that the above value would represent the lowercase character f
. Below, is an illustration of how a byte stream representing textual data might appear.
Note: In the illustration above, the solid black boxes separating 8-bit groups are purely for visualization purposes only. Such a gap in information would not be present in practice.
Byte Stream Example in Java
Java is one of the most utilized programming languages in the world and, as one might expect, has great affordance for working with byte streams. Java provides a high-level API for streaming bytes between data sources. Below, see an example of using Java’s FileInputStream
and FileOutputStream
classes to copy the contents of input.txt
to output.txt
:
// Define I/O streams FileInputStream inStream; FileOutputStream outStream; // Get input stream inStream = new FileInputStream("input.txt"); // Get output Stream outStream = new FileOutputStream("output.txt"); // Stream input, write to output int next; // the next character in the byte stream while((next = inStream.read()) != -1){ // Write next character outStream.write(next); }
In the code above, a file named input.txt
is opened and read byte by byte and written to a file object (via byte stream) until the value -1
is reached (java for no more bytes). The end result being that input.txt
is copied to output.txt
. The approach above is subject to IOExceptions and should be handled appropriately.
Note: Byte streams should always be closed after use to ensure no memory leaks. A more complete version of the above code, demonstrating proper close()
method calls, can be found on GitHub.
Byte streams are used when the nature of data isn’t certain. In cases where textual data is being streamed, languages like Java offer character-streaming classes. These constructs can be useful in network programming where users input character-based data that is then sent over the network, which is transmitted as bits.
Discussion
There is much to consider when it comes to bits, bytes, and the streaming of either. Modern network communications rely heavily on protocols largely concerned with the transmission of bits.
In fact, network communications are so bitstream oriented that line “speeds” are measured in bitrate commonly denoted as Megabits per second (Mbps).
The examples here are as basic as it gets—meant only to be an introduction to the topic of bits, bytes, and byte streams.