Showing posts with label Streams. Show all posts
Showing posts with label Streams. Show all posts

2008/03/18

Stream Abstraction

A common abstraction used for I/O is a "stream." A stream is a reliable connection between two components through which one device can send data to the other. Streams usually operate on bytes (and are called byte streams).

A stream gets it's name because it is like a river of data. The data length is unknown, and you cannot randomly access elements in the stream. When data is added to the stream it flows down the river. You are only allowed to insert data at the start of the stream -- you cannot change it, remove it, or insert something ahead of it -- once it has gone into the stream, it is out of your control. When you remove data from a stream, you can only remove it from the end. You cannot "go back" in the stream (doing so would be the same as pushing a river backwards) and you cannot read a value later in the stream (without reading the data earlier in the stream). The data pours out of the end, and once it is removed, it is no longer part of the stream.

Imagine a stream as a river, and your program is using it to send/receive messages. Putting data in the stream is the same as putting a message into a bottle and floating it down the river. Taking data from the stream is the same as removing a bottle from the river. However, in this case the river is a perfect delivery mechanism. Bottles always arrive in the same order that they were sent, they are never lost (or missed), and there are no gaps between the bottles.

Output streams are occasionally called a "sink," whereas input streams are sometimes called a "source."

Streams are a useful abstraction because they hide the underlying transport mechanism used between components, and they hide the details of the component at the other end. The stream could be a network socket, a pipe to another program, a terminal, a keyboard, a disk, a printer, a modem, a billboard, or a buffer in memory. Programs written to use streams as their I/O can be easily adapted to substitute one implementation of a stream for another.

See: Java's InputStream, OutputStream, C++'s iostream, and C's I/O with streams (stdio.h).