Reading character streams in Java
Java InputStreams are generally designed to
read "raw" byte data from a file or stream. They're not generally suitable or convenient
for reading character data for a couple of reasons:
- it would then be the coder's responsibility to convert bytes to characters
correctly: depending on the character encoding, there's not always a one-to-one correspondence
between a byte and a character, and in any case the correspondence depends on the encoding used;
- it would be the coder's responsibility to deal with line breaks correctly.
Java Readers
The equivalent of a character input stream in Java is a Reader.
The abstract class Reader has various concrete flavours, of which an important
examples is InputStreamReader. To start pulling characters from an input stream,
we use the concept of stream wrapping that we saw with
input stream buffering. In other words,
we wrap an InputStream in an InputStreamReader, also passing in
the character encoding of the stream. To pull successive characters
from the stream, we then call the Reader's read() method:
InputStream in = new FileInputStream("charfile.txt");
Reader r = new InputStreamReader(in, "US-ASCII");
int intch;
while ((intch = r.read()) != -1) {
char ch = (char) intch;
// ...
}
For simplicity, we've not included exception handling in the above example.
Note that the Reader.read() method behaves very similary to that of
InputStream: it returns the next character as an int,
which we must cast to a char ourselves. This is because when
the end of the stream is reached, -1 is
returned just as with a InputStream.read().
Buffering with BufferedReader
In practice, it's common to further wrap an InputStreamReader in a
BufferedReader to improve performance.
Here is an example method to count the number of letters in an ASCII text file:
public int countASCIILetters(File f) throws IOException {
Reader r = new BufferedReader(new InputStreamReader(
new FileInputStream(f), "US-ASCII"));
try {
int count = 0;
int intch;
while ((intch = r.read()) != -1) {
int ch = (char) intch;
if (Character.isLetter(ch)) {
count++;
}
}
return count;
} finally {
r.close();
}
}
On the next page, we'll look at another important feature of
BufferedReader: allowing you to read a
line at a time from a file or character stream.
If you enjoy this Java programming article, please share with friends and colleagues. Follow the author on Twitter for the latest news and rants.
Editorial page content written by Neil Coffey. Copyright © Javamex UK 2021. All rights reserved.