1. OutputStream class

We just recently explored input streams. It's time to talk about output streams.

The OutputStream class is the parent class for all classes that support byte output. This is an abstract class that does nothing on its own, but it has descendant classes for every occasion.

It sounds extremely complicated. To put it more simply, this class operates on bytes, and not, for example, characters or other data types. And the fact that it is abstract means that we usually do not use it, but rather one of its descendant classes. For example, FileOutputStream and the like.

But back to the OutputStream class. This class has methods that all its descendant classes must implement. Here are the main ones:

Methods Description
void write(int b)
Writes one byte (not an int) to the stream.
void write(byte[] buffer)
Writes an array of bytes to the stream
void write(byte[] buffer, off, len)
Writes part of an array of bytes to the stream
void flush()
Writes all the data stored in the buffer to the stream
void close()
Closes the stream

When you create an object of a class that inherits InputStream, you usually specify a source object that the InputStream reads data from. When you create an object of a class that inherits OutputStream, you also usually specify the target object or stream that data will be written to.

Let's briefly go through all the methods of the OutputStream class:

write(int b) method

This method writes one byte (not an int) to the output stream. The passed value is cast to a byte, and the int's first three bytes are discarded.

write(byte[] buffer) method

Writes the given array of bytes to the output stream. That's it.

write(byte[] buffer, int offset, int length) method

Writes a portion of the passed array of bytes to the output stream. The offset variable indicates the index of the first element of the array, and length is the length of the subset to be written.

flush() method

The flush() method is used to force any data potentially buffered in the current stream to be written to the target stream. This is relevant when using buffering and/or multiple stream objects arranged in a chain.

close() method

Writes any unwritten data to the target object. The close() method need not be called if you use a try-with-resources block.

Example of copying a file

Code Note
String src = "c:\\projects\\log.txt";
String dest = "c:\\projects\\copy.txt";

try(FileInputStream input = new FileInputStream(src);
FileOutputStream output = new FileOutputStream(dest))
{
   byte[] buffer = new byte[65536]; // 64Kb
   while (input.available() > 0)
   {
      int real = input.read(buffer);
      output.write(buffer, 0, real);
   }
}



InputStream for reading from a file
OutputStream for write to a file

Buffer into which we will read the data
As long as there is data in the stream

Read data into the buffer
Write the data from the buffer to the second stream

2. Writer class

The Writer class is exactly the same as the OutputStream class, but just one difference once again: it works with characters (char) instead of bytes.

This is an abstract class: you cannot create objects of the Writer class. Its main goal is to be a common parent class for hundreds of descendant classes and to give them common methods for working with character streams.

Methods of the Writer class (and all its descendant classes):

Methods Description
void write(int b)
Writes one character (not an int) to the stream.
void write(char[] buffer)
Writes an array of characters to the stream
void write(char[] buffer, off, len)
Writes part of an array of characters to the stream
void write(String str)
Writes a string to the stream
void write(String str, off, len)
Writes part of a string to the stream
void flush()
Writes all the data stored in the buffer to the stream
void close()
Closes the stream

The methods are very similar to the methods of the OutputStream class, but they work with characters instead of bytes.

Description of methods:

write(int b) method

This method writes a single character (char — not an int) to the output stream. The passed value is cast to a char, and the first two bytes are discarded.

write(char[] buffer) method

Writes the given array of characters to the output stream.

write(char[] buffer, int offset, int length) method

Writes a portion of the passed array of characters to the output stream. The offset variable indicates the index of the first element of the array, and length is the length of the subset to be written.

write(String str) method

Writes the given string to the output stream.

write(String str, int offset, int length) method

Writes a portion of the given string to the output stream: the string is converted to an array of characters. The offset variable indicates the index of the first element of the array, and length is the length of the subset to be written.

flush() method

The flush() method is used to force any data potentially buffered in the current stream to be written to the target stream. This is relevant when using buffering and/or multiple stream objects arranged in a chain.

close() method

Writes any unwritten data to the target object. The close() method need not be called if you use a try-with-resources block.

Example of a program that copies a text file:

Code Note
String src = "c:\\projects\\log.txt";
String dest = "c:\\projects\\copy.txt";

try(FileReader reader = new FileReader(src);
FileWriter writer = new FileWriter(dest))
{
   char[] buffer = new char[65536]; // 128Kb
   while (reader.ready())
   {
      int real = reader.read(buffer);
      writer.write(buffer, 0, real);
   }
}



Reader for reading from a file
Writer for writing to a file

Buffer into which we will read the data
As long as there is data in the stream

Read data into a buffer
Write the data from the buffer to the second stream

StringWriter class

There is another interesting class that inherits the Writer class: it is called StringWriter. It contains a mutable string — a StringBuffer object. And every time you "write" something to the StringWriter object, the text is simply added to its internal buffer.

Example:

Code Note
StringWriter writer = new StringWriter();
writer.write("Hello");
writer.write(String.valueOf(123));

String result = writer.toString();
A target character stream (StringWriter) is created
A string is written to the buffer inside the StringWriter
A string is written to the buffer inside the StringWriter

Converting the contents of an object into a string

In this case, the StringWriter class is essentially a wrapper over the StringBuffer class, but the StringWriter class is a descendant of the Writer stream class, and it can be used in chains of stream objects. This is a pretty useful property in practice.


undefined
16
Task
New Java Syntax, level 16, lesson 4
Locked
Dividing by zero
Create a public static void divideByZero method that divides any number by zero, and display the result of the division. Wrap the divideByZero method call in a try-catch block. Display the exception stack trace using the exception.printStackTrace() method
undefined
16
Task
New Java Syntax, level 16, lesson 4
Locked
Countdown from 5 to 0
The loop counts down from 5 to 0. Add a delay using Thread.sleep(100); Wrap the sleep call in a try-catch block.

3. PrintStream class

Output stream classes can also be put into a chain with intermediary streams that write data to the target stream passed to them. The general view of the interaction of these streams looks like this:

PrintStream class

The most interesting and versatile of all intermediate output streams is PrintStream. It has tens of methods and as many as 12 constructors.

The PrintStream class inherits the FilterOutputStream class, which inherits OutputStream. That means that the PrintStream class has all the methods of the parent classes in addition to its own methods. Here are the most interesting ones:

Methods Description
void print(obj)
Converts the passed object to a string and outputs it to the target stream.
void println(obj)
Converts the passed object to a string and outputs it to the target stream. Adds a line break at the end
void println()
Outputs a line break character to the target stream
PrintStream format(String format, args...)
Constructs and outputs a string based on the format string and the passed arguments; similar to the String.format() method

And where are these tens of methods, you ask?

Well, it has many variants of the print() and println() methods with different parameters. They can be summarized in this table.

We won't dive into these methods, because you already know them well. Can you guess what I'm getting at?

Remember System.out.println()? But it can be written in two lines:

Code Console output
PrintStream stream = System.out;
stream.println("Hello!");
Hello!

Our favorite command System.out.println() is a call to the println() method on the static out variable of the System class. And this variable's type is PrintStream.

In lots of CodeGym levels, and in almost every task, you have been calling methods of the PrintStream class without even knowing it!

Practical use

Java has this interesting class called ByteArrayOutputStream, which is a dynamically growing byte array that inherits OutputStream.

A ByteArrayOutputStream object and PrintStream object can be chained like this:

Code Description
ByteArrayOutputStream baos = new ByteArrayOutputStream();

try(PrintStream stream = new PrintStream(baos))
{
   stream.println("Hello");
   stream.println(123);
}

String result = baos.toString();

System.out.println(result);
Create a write buffer in memory

Wrap the buffer in a PrintStream object

Write data to the console



Convert the array to a string!

Console output:
Hello!
123

undefined
16
Task
New Java Syntax, level 16, lesson 4
Locked
Throwing exceptions
There are four non-static methods: method1(), method2(), method3(), method4(). Using the throws keyword, make it so that method1() and method2() throw any checked exception, and method3() and method4() throw an unchecked exception.
undefined
16
Task
New Java Syntax, level 16, lesson 4
Locked
Vowels and consonants
Write a program that reads a string from the keyboard. The program should display two lines: 1. The first line contains only the vowels from the entered string. 2. The second contains only the consonants and punctuation marks from the entered string. The letters should be separated by a space, each
undefined
16
Task
New Java Syntax, level 16, lesson 4
Locked
A scary fairy tale
1. Once there were five classes: red riding hood, grandmother, pie, woodcutter, and wolf. 2. Each class has 2 fields: ArrayList killed and ArrayList ate. 3. The necessary objects have been created (hood, grandmother, ...). 4. Arrange the relationships correctly according to who ate and/or killed who
undefined
16
Task
New Java Syntax, level 16, lesson 4
Locked
Static modifiers are out of place
Rearrange the static modifiers so that the program compiles.
undefined
16
Task
New Java Syntax, level 16, lesson 4
Locked
List of number arrays
In the createList method: - create a list whose elements are arrays of numbers; - add to the list five array objects whose lengths are 5, 2, 4, 7, and 0, respectively; - fill the arrays with any data.
undefined
16
Task
New Java Syntax, level 16, lesson 4
Locked
Ten cats
There is a Cat class with a String variable name. Create a Map and add 10 cats represented by (name, Cat) pairs. Get a Set of all cats from the Map. Display the set on the screen (already implemented).
undefined
16
Task
New Java Syntax, level 16, lesson 4
Locked
Task about algorithms
The program reads words and numbers from the keyboard, adds them to a list, converts the list to an array, and then displays the array on the screen. Sort the array so that words appear in ascending order and numbers appear in descending order. Example input: Cherry 1 Bob 3 Apple 22 0 Watermelon E