We can create streams of data from files, network resources, memory locations, etc, both input and output. To initially demonstrate the use of streams, we'll use streams around a file, both byte and Character streams. The methods introduced in these example can be used for any stream.
InputStreams and OutputStreams are streams of bytes:
Readers and Writers are streams of Characters:
When we write to an output stream or writer such as FileWriter, we should always close() it in some way:
We can choose from many such methods to read and write characters to streams, where the stream is always closed automatically. Here's some methods which use a Reader and/or Writer. Although these examples use Files, all these methods work for other streamed resources also.
Some methods which use an input and/or output stream which, although using Files in the examples, all work for other streamed resources also:
Although the examples above are for files, they're all available for streams, readers, and writers around all other resources also.
When we met the FileInputStream, FileOutputStream, FileReader, and FileWriter in the above examples, we constructed them with a single String. We can also construct them with a file, and add an 'append' flag:
There are many other streams, readers, and writers that wrap around specific resources. ByteArrayInputStream and ByteArrayOutputStream wrap around an array of bytes:
CharArrayReader and CharArrayWriter wrap around an array of chars:
StringReader and StringWriter wrap around a StringBuffer:
InputStreamReader and OutputStreamWriter are a reader and writer pair that forms the bridge between byte streams and character streams. An InputStreamReader reads bytes from an InputStream and converts them to characters using a character-encoding, either the default or one specified by name. Similarly, an OutputStreamWriter converts characters to bytes using a character-encoding and then writes those bytes to an OutputStream. In this example, we use a FileInputStream and FileOutputStream, but any InputStream or OutputStream could be used:
The buffered streams, reader, and writer wrap around another, buffering the data read or written so as to provide for the efficient processing of bytes, characters, arrays, and lines. It's very useful for streams, readers, and writers whose input/output operations are costly, such as files.
A SequenceInputStream joins two other streams together:
SequenceInputStream can also join three or more streams together using a Vector. See the upcoming tutorial on multi-threading for more on Vectors:
A line-number reader keeps track of line numbers:
A pushback input stream allows read input to be pushed back on:
A pushback reader provides a similar facility for characters:
A DataOutputStream writes out Groovy structures as bytes, and a DataInputStream reads such bytes in as Groovy structures:
We'll meet more different types of streams, readers, and writers in the tutorials on Inheritance, Networking, Multi-threading, and others coming up.
There are also helper methods for Object input/output classes as this example shows: