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.