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, | 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, | 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, | 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.
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.
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.
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, | 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.
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.
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.