Character Stream ClassesJ8 Home « Character Stream Classes

In our final lesson on Java I/O we take a closer look at some of the character stream classes that are available in Java and how we use them.

Although byte stream classes offer us a lot of efficiency and flexibility when dealing with bytes and binary data, they are not the best way to handle character input and output. Character streams operate directly on Unicode characters and so for storing and retrieval of Unicode text for internationalisation character streams are a better altrenative to byte streams. For this reason the character stream classes were introduced to the language in JDK 1.1 to offer a more efficient and easier way of dealing with character-based I/O.

The java.io.Writer Class Top

At the top of the character output stream hierarchy is the java.io.Writer abstract superclass which defines a basic set of output functions that all character output stream classes have. These methods allow us to append, flush and write bytes within the character output stream as well as close the stream when we finish our processing. All methods within the java.io.Writer class can throw an IOException.

The table below shows the declarations of all the methods in the java.io.Writer class:

Method Declaration Description
public Writer append(char c)Appends the specified character to the end of the invoking Writer stream and returns a reference to the invoking Writer stream.
public Writer append(CharSequence chars) Appends the specified characters to the end of the invoking Writer stream and returns a reference to the invoking Writer stream.
public Writer append(CharSequence chars,
int start,
int end)
Appends the specified character sequence specified by the start and end arguments to the end of the invoking Writer stream and returns a reference to the invoking Writer stream.
public abstract void close()Closes output stream and release any system resources associated with it.
public abstract void flush()Flushes output stream and forces any buffered output bytes to be written out.
public void write(int ch)Writes a single character of data to the output stream.
public void write(char[] chbuff)Writes an array of characters.
public abstract void write(char[] chbuff,
int offset,
int length)
Writes length bytes of data from chbuff array starting from offset.
public void write(String str)Writes a string of data specified by str to the output stream.
public void write(String str,
int offset,
int length)
Writes part of a string of data specified by str starting at offset for length.

The java.io.PrintWriter Class Top

We saw in the Byte Stream Classes lesson how we can write bytes to the console using the write(bytes[]) method. This worked fine because we only used characters from the standard 8-bit ASCII character set which has a range of 0 to 127. If we had tried to run our example with any character outside this range we would have got a possible loss of presision compiler error because we can't fit char types into one byte. This is fine for writing output from sample programs such as those used on this site but we can see the limitations. For more verbose applications and proper internationalisation we need to use the full Unicode character set which has a range 0 to 65,536 and for this we need to use a character output stream.

To write to the console we will use the PrintWriter class and upon inspection of the constructors for this class in the online version of documentation JavaTM 2 Platform Standard Edition 5.0 API Specification we can see that the PrintWriter class accepts a File, OutputStream, String or Writer objects as a parameter. There are two constructors that use an existing OutputStream which is just what we want to wrap our PrintWriter class in so we can write to the console. If you remember from the Java I/O Overview lesson we write to the console using System.out which is a PrintStream type, which is a subclass of OutputStream. We will also use the constructor with the autoflush option and set this to true so the stream gets automatically flushed.

Writing Characters To The Console Top

For our example of using the java.io.PrintWriter class we will create a File object in our working directory and write some data to the file:


package info.java8;
/*
  Write character sequence output to the console using PrintWriter
*/
import java.io.*; // Import all file classes from java.io package

class TestPrintWriter {
    public static void main(String[] args) {
        char someData[] = new char[]{'J','a','v','a','6'};
        char someData2[] = new char[]{'J','á','v','á','6'}; 
        double d = 128.128;

        PrintWriter pw = new PrintWriter(System.out, true); // Create a PrintWriter stream to console
        System.out.println("PrintWriter pw has been opened.");
        pw.println("Writing a string with PrintWriter.");
        pw.println("Writing a char array with PrintWriter: " + someData);
        pw.println("Writing an internationalized char array with PrintWriter: " + someData2);
        pw.println("Writing a double primitive with PrintWriter: " + d);
    }
}

Save, compile and run the TestPrintWriter test class in directory   c:\_APIContents2 in the usual way.

run test printwriter

The above screenshot shows the output of compiling and running the TestPrintWriter class. We print some messages to the console via the PrintWriter class, making sure that the stream is automatically flushed.

As a side note this isn't a very efficient way to use the PrintWriter class as it would be better to wrap this class in a BufferedWriter class so output gets written when the buffer is full.

The java.io.FileWriter Class Top

We saw above how we can write information to the console using the The java.io.PrintWriter class. This doesn't really offers us anything practical when it comes to storing information on the underlying file system. Luckily for us the subclasses in the character output stream hierarchy give us ways to persist our data. In this part of the lesson we examine the java.io.FileWriter class which allows us to output data to a file on the system. Ordinarily we would use this class as a wrapper for other character output stream classes but we will show it here to see how it can be used in its basic form.

Writing Character Data To A File Top

For our example of using the java.io.FileWriter class we will create a File object in our working directory. We then accept user input until 'end' is entered using the BufferedReader class and write each user entry to a file using the FileWriter class:


package info.java8;
/*
  Write user input to a file using FileWriter
*/
import java.io.*; // Import all file classes from java.io package

class TestFileWriter {
    public static void main(String[] args) throws IOException {
        FileWriter fw;
        String str;
        File newFile  = new File("FileWriter.txt");
        // Open FileWriter.txt and output user input to it
        try {
            fw = new FileWriter(newFile); // Create a stream to write to FileWriter.txt
            System.out.println("FileWriter fw has been opened.");
            // Create a BufferedReader wrapped in InputStreamReader stream
            BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
            System.out.println("BufferedReader br has been opened.");
            do {
                str = br.readLine();
                System.out.println("I typed in: " + str + ". Type in 'end' to quit");
                // Check for stop condition
                if (str.compareTo("end") == 0) {
                    break;
                }   
                str = str + "\r\n";
                fw.write(str);
            } while (str.compareTo("end") !=0); 
            System.out.println("I typed in 'end'");
            fw.close();
        }
        catch (IOException ex) {
            System.out.println("Exception opening FileWriter.txt : " + ex);
        }
    }
}

Save, compile and run the TestFileWriter test class in directory   c:\_APIContents2 in the usual way.

run test filewriter

The above screenshot shows the output of compiling and running the TestFileWriter class. We print some messages to the console as we create our streams and then output all console input to a file.

The java.io.BufferedWriter Class Top

We saw above how we can write native I/O to a file using the FileWriter class but there is an easier and more efficient option for writing text to a file. Without buffering, each invocation of a write() method would cause characters to be converted into bytes that are written immediately to a file, which can be very inefficient. Looking at the subclasses available in the character output stream hierarchy we can see there is a BufferedWriter class which offers us a much easier way to write out textual data. This class allows us to write strings of text and even comes with a handy method to create a new line.

Writing Buffered Data To A File Top

For our example of using the java.io.BufferedWriter class we will create a File object in our working directory and open up a BufferedWriter stream wrapped in a FileWriter stream. We then write parts of some strings and use the newLine() method to make sure each string appears on a new line:


package info.java8;
/*
  Write strings to a file using BufferedWriter
*/
import java.io.*; // Import all file classes from java.io package

class TestBufferedWriter {
    public static void main(String[] args) throws IOException {
        BufferedWriter bw = null;
        String str1 = "The quick brown fox jumps over the lazy dog";
        String str2 = "A stitch in time saves nine";
        File newFile  = new File("BufferedWriter.txt");
        // Open BufferedWriter.txt and output some strings to it
        try {
            // Create a BufferedReader wrapped in a FileWriter stream
            bw = new BufferedWriter(new FileWriter(newFile));
            System.out.println("BufferedWriter bw has been opened.");
            // Start writing to the BufferedWriter stream
            bw.write(str1, 0, 10);
            bw.newLine();
            bw.write(str2, 5, 10);
        }
        catch (IOException ex) {
            System.out.println("Exception opening BufferedWriter.txt : " + ex);
        }
        finally {
            bw.flush();
            System.out.println("BufferedWriter flushed");
            bw.close();
            System.out.println("BufferedWriter closed");
        }
    }
}

Save, compile and run the TestBufferedWriter test class in directory   c:\_APIContents2 in the usual way.

run test bufferedwriter

The above screenshot shows the output of compiling and running the TestBufferedWriter class. We print some messages to the console as we create our streams and then output portions of strings to a file.

The java.io.Reader Class Top

At the top of the character input stream hierarchy is the java.io.Reader abstract superclass which defines a basic set of input functions that all character input stream classes have. These methods allow us to mark, read, ready, reset and skip characters within the character input stream as well as close the stream when we finish our processing. All methods within the java.io.Reader class can throw an IOException.

The table below shows the declarations of all the methods in the java.io.Reader class:

Method Declaration Description
public abstract void close()Closes input stream and release any system resources associated with it.
public void mark(int readlimit)Mark current stream position to which we can return until readlimit has been reached.
public boolean markSupported()Returns true if invoking stream supports mark() and reset() methods.
public abstract int read()Reads next character of data from input stream or -1 if end of file encountered.
public int read(char[] chbuff)Reads characters of data into chbuff array.
public abstract int read(char[] chbuff,
int offset,
int length)
Reads length characters of data into chbuff array starting from offset.
public int read(CharBuffer buffer)Attemps to fill specified CharBuffer.
public void ready()Returns true if streamy is ready to read from.
public boolean reset()Reset the input pointer to the last mark() position.
public long skip(long skipChars)Skip number of characters specified by skipChars and return skipChars.

The java.io.BufferedReader Class Top

We saw in the Byte Stream Classes lesson how we can read bytes from the console using the read() and read(bytes[]) methods. This worked fine because we only used characters from the standard 8-bit ASCII character set which has a range of 0 to 127. If we had tried to run our example with any character outside this range we would have got some very strange results and you might want to go back to the code we wrote and try inputting a character such as á. This will return -96131 followed by lots of zeros or the ? character when cast to a char type. For more verbose applications and proper internationalisation we need to use the full Unicode character set which has a range 0 to 65,536 and for this we need to use a character input stream.

So to read characters from the console we need a class to convert byte streams into character streams and from looking at the character input stream hierarchy we can see that the InputStreamReader class acts as a bridge for decoding byte streams into character streams which is exactly what we want. Closer inspection of the online version of documentation JavaTM 2 Platform Standard Edition 5.0 API Specification for the InputStreamReader class suggests that for top efficiency, we should wrap the InputStreamReader within a BufferedReader and for our example that is exactly what we will do.

Read Characters From The Console Top

Lets see how we could use the BufferedReader class to get a sequence of characters from the keyboard:


package info.java8;
/*
  Read character sequence from the keyboard using BufferedReader
*/
import java.io.*; // Import all file classes from java.io package

class TestBufferedReader {
    public static void main(String[] args) throws IOException {
        String str;
         // Create a BufferedReader wrapped an InputStreamReader stream
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        System.out.println("BufferedReader br has been opened.");
        do {
            str = br.readLine();
            System.out.println("I typed in: " + str + ". Type in 'end' to quit");
        } while (!str.equals("end")); 
        System.out.println("I typed in 'end'");
    }
}

Save, compile and run the TestBufferedReader test class in directory   c:\_APIContents2 in the usual way.

run test bufferedreader

The above screenshot shows the output of compiling and running the TestBufferedReader class. Our program accepts whatever character input we give it and erads a line of keyboard input at a time using the readLine() method. We can continue reading input from the keyboard ad infinitum until we enter 'end' to terminate the program.

The java.io.FileReader Class Top

We saw above how we can read character input from the keyboard using the The java.io.BufferedReader class. This doesn't really offers us anything practical when it comes to reading information from the underlying file system. Luckily for us the subclasses in the character input stream hierarchy give us ways to read our persisted data. In this part of the lesson we examine the java.io.FileReader class which offers us methods to read existing files on the system.

Read Characters From A File Top

For our example of using the java.io.FileReader class we will we will create a File object to read the FileWriter.txt file we created in the java.io.FileWriter section above. Using the FileReader class as we do below is quite cumbersome and it is far better to use this class as a wrapper for other classes such as BufferedReader:


package info.java8;
/*
  Read input a file using FileReader
*/
import java.io.*; // Import all file classes from java.io package

class TestFileReader {
    public static void main(String[] args) throws IOException {
        FileReader fr; // Our FileReader
        char[] store = new char[100];
        int size = 0;
        String str;
        File newFile  = new File("FileWriter.txt");
         // Open FileWriter.txt and read data from it
        fr = new FileReader(newFile); // Create a stream to read from FileWriter.txt
        System.out.println("FileReader fr has been opened.");
        size = fr.read(store); // read in whole file
        System.out.println(size);
        for (char c : store) {
            System.out.print(c);
        }
        fr.close();
    }
}

Save, compile and run the TestFileReader test class in directory   c:\_APIContents2 in the usual way.

run test filereader

The above screenshot shows the output of compiling and running the TestFileReader class. We print some messages to the console and store all characters read from the file in an array and write them to the console.

Lesson 3 Complete

In this lesson we looked at some of the Character stream classes that are available in Java and how we use them.

What's Next?

In the next lesson we we start a new section on Collections/Generics with an overview of the collections framework.