Java I/O Streams: Input, Output and Wrapping (Decorator) Explained - Quiz
Total: 5 questions
1. What is a stream in Java I/O, and what kinds of I/O streams are there?
What is a stream in Java I/O, and what kinds of I/O streams are there?
A stream is an ordered sequence of bytes or characters that flows between a program and a source or destination of data: a file, the console, a network connection, an array in memory. The program reads and writes through the same read() and write() methods without knowing what device is on the other end. Stream classes live in the java.io package.
Streams are classified by two criteria:
- by data type — byte streams (8-bit bytes, suitable for any data: images, archives) and character streams (
charvalues, UTF-16, for text); - by direction — input streams (reading) and output streams (writing).
Combined, they give four basic abstract classes: InputStream and OutputStream (byte), Reader and Writer (character). The suffix tells the kind: ...Stream is a byte stream, ...Reader/...Writer a character stream. A file always holds bytes: a character stream is a byte stream plus a charset.
2. How is an I/O stream (InputStream) different from a Stream API stream and from a Thread?
How is an I/O stream (InputStream) different from a Stream API stream and from a Thread?
The names overlap, but these are three unrelated things:
- I/O stream (
InputStream,OutputStream,Reader,Writerfromjava.io) — a sequence of bytes or characters between a program and a file, console or network. Example:new FileInputStream("photo.jpg"). - Stream API (
java.util.stream.Stream, Java 8) — a pipeline of operations over the elements of a collection or array; it does not read anything from disk on its own. Example:list.stream().filter(...).count(). - Thread (
java.lang.Thread) — a separate path of execution that runs concurrently with other code.
FileInputStream does not extend Stream and does not start a Thread. The only point of contact is BufferedReader.lines(), which turns the lines of an I/O stream into a Stream<String>.
3. What are the steps of working with any I/O stream in Java?
What are the steps of working with any I/O stream in Java?
Three steps:
- Create a stream object and connect it to a source or destination of data (a file, a socket, an array).
- While there is data, read it from the stream or write it to the stream. A byte
read()returns-1when the data runs out. - Close the stream — to release the operating system resource and flush buffers.
In modern code the third step is done by try-with-resources (Java 7+): the stream is closed automatically, even if an exception occurs inside.
try (InputStream in = new FileInputStream("data.bin")) { // 1. open
int b;
while ((b = in.read()) != -1) { // 2. read until -1
// process byte b
}
} // 3. close() is called automatically
4. What is wrapping streams in Java, and how is it related to the decorator pattern?
What is wrapping streams in Java, and how is it related to the decorator pattern?
Wrapping means passing one stream into the constructor of another so that it gains new abilities: buffering, reading lines, formatted output, converting bytes to characters. The outer stream (the wrapper) delegates the real reading and writing to the inner one.
PrintWriter printer = new PrintWriter(new BufferedWriter(new FileWriter("log.txt")));
Here FileWriter writes to the file, BufferedWriter collects characters in a buffer, and PrintWriter adds println() and printf().
This is the decorator pattern: a wrapper has the same type as the stream it wraps (BufferedReader is also a Reader), so wrappers can be nested in any order without a separate class for every combination. In java.io you can see it in the base classes FilterInputStream, FilterOutputStream, FilterReader, FilterWriter: they hold a reference to the inner stream and by default pass all calls to it.
5. How do you read a text file line by line in a given charset through a chain of wrappers, and which wrapper in the chain should you close?
How do you read a text file line by line in a given charset through a chain of wrappers, and which wrapper in the chain should you close?
Wrap the byte stream in an InputStreamReader (the bridge from bytes to characters with a given charset), and wrap that in a BufferedReader (a buffer and the readLine() method, which returns null at the end of the stream):
try (BufferedReader reader = new BufferedReader(
new InputStreamReader(
new FileInputStream("notes.txt"), StandardCharsets.UTF_8))) {
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
}
Specify the charset explicitly: without a Charset the default charset is used, which up to and including Java 17 depended on the OS (since Java 18 it is UTF-8).
Close only the outermost wrapper: its close() first flushes its own buffer, then closes the inner stream, and so on down to the file. If the inner stream is closed before the outer one, the data in the wrapper's buffer is lost and the wrapper's close() throws IOException: Stream closed.