Tutorials     About     RSS
Tech and Media Labs

Java PushbackReader

Jakob Jenkov
Last update: 2019-09-26

The Java PushbackReader class, java.io.PushbackReader, is intended to be used when you parse data from a Reader. Sometimes you need to read ahead a few characters to see what is coming, before you can determine how to interpret the current character. The Java PushbackReader allows you to do that. Well, actually it allows you to push back the read characters into the Reader. These characters will then be read again the next time you call read().

The Java PushbackReader works much like the PushbackInputStream except that the PushbackReader works on characters, whereas the PushbackInputStream works on bytes.

PushbackReader Example

Here is a simple PushbackReader example:

PushbackReader pushbackReader =
    new PushbackReader(new FileReader("c:\\data\\input.txt"));

int data = pushbackReader.read();

pushbackReader.unread(data);

The call to read() reads a character from the PushbackReader just like from any other Reader. The call to unread() pushes a character back into the PushbackReader. The next time read() is called the pushed back characters will be read first. If you push back multiple characters into the PushbackReader, the latest pushed back character will be returned first from the read() method, just like with a stack.

Create a PushbackReader

To use a Java PushbackReader you must first create a PushbackReader instance. You create a PushbackReader using standard object instantiation - using the new operator. To the PushbackReader constructor you must pass a Java Reader from which the PushbackReader will read its characters. Here is an example of creating a Java PushbackReader:

PushbackReader pushbackReader =
    new PushbackReader(new FileReader("c:\\data\\input.txt"));

This example passes a Java FileReader to the PushbackReader constructor. This will make the PushbackReader read its characters from this FileReader.

Setting the Push Back Limit of a PushbackReader

You can set the number of characters you should be able to unread in the constructor of the PushbackReader. Here is how to set the pushback limit using the PushbackReader constructor:

int pushbackLimit = 8;
PushbackReader reader = new PushbackReader(
                                new FileReader("c:\\data\\input.txt"),
                                pushbackLimit);

This example sets an internal buffer of 8 characters in the PushbackReader. That means you can unread at most 8 characters at a time, before reading them again.

Read Characters

You read characters from a Java PushbackReader just like you do from a Java Reader - because PushbackReader is a Java Reader subclass. In other words, you use its read() method which is inherited from the Reader class. Here is an example of reading characters from a Java PushbackReader via its read() method:

int aChar = pushbackReader.read();
while(aChar != -1) {
    System.out.println((char) aChar);
    aChar = pushbackReader.read();
}

The read() returns an int which you will have to cast to a char yourself, as shown in the example above. When there are no characters available in the PushbackReader the read() method will return the int value -1.

Push Back Characters

To push a character back into a Java PushbackReader you must call its unread() method. Here is an example of pushing back a character into a PushbackReader :


int aChar = pushbackReader.read();

pushbackReader.unread(aChar);

aChar = pushbackReader.read(); // reads character pushed back

This example reads a character from a PushbackReader, then pushes it back into the PushbackReader, and then reads that character from the PushbackReader again.

Closing a PushbackReader

When you are finished reading characters from the PushbackReader you should remember to close it. Closing a PushbackReader will also close the Reader instance from which the PushbackReader is reading.

Closing a PushbackReader is done by calling its close() method. Here is how closing a PushbackReader looks:

pushbackReader.close();

You can also use the try-with-resources construct introduced in Java 7. Here is how to use and close a PushbackReader looks with the try-with-resources construct:

Reader reader = new FileReader("data/data.bin");

try(PushbackReader pushbackReader =
    new PushbackReader(reader)){

    int data = pushbackReader.read();
    while(data != -1) {
        System.out.print((char) data);
        data = pushbackReader.read();
    }
}

Notice how there is no longer any explicit close() method call. The try-with-resources construct takes care of that.

Notice also that the first FileReader instance is not created inside the try-with-resources block. That means that the try-with-resources block will not automatically close this FileReader instance. However, when the PushbackReader is closed it will also close the Reader instance it reads from, so the FileReader instance will get closed when the PushbackReader is closed.

Parsing Example

At the end of this Java PusbackReader tutorial, lets see a slightly more elaborate example of how you can use the PushbackReader when parsing a stream of characters. This example samples the first character of the next "token" to be read from a PushbackReader to determine the type of the next token, then pushes back the character for the corresponding tokenizer to read. The example is a bit "constructed" for the occasion, meaning in a real parser you might do things a bit differently. However, the example serves mostly to show how the PushbackReader can be used in a real parsing example, not as a text book example of writing great parsers.

public class TextTokenizer {
    protected PushbackReader pushbackReader =  null;

    public TextTokenizer(Reader reader) {
        this.pushbackReader = new PushbackReader(reader);
    }

    public String nextToken() {
        int firstChar = this.pushbackReader.read();
        this.pushbackReader.unread(firstChar);

        if(((char)firstChar) == '"') {
           return readDoubleQuotedToken();
        }
        if((char)firstChar) == '\'') {
           return readSingleQuotedToken();
        }
        return readSingleWordToken();
    }

    protected String readDoubleQuotedToken() { ... }

    protected String readSingleQuotedToken() { ... }

    protected String readSingleWordToken()   { ... }
}

The interesting part of this example is the nextToken() method. This method first reads a character from the PushbackReader into a variable, then pushes the read character back into the PushbackReader. This way the nextToken() method can "sample" the first character of the next token, and based on that decide what kind of token it is, and what read method to call for that kind of token.

Note, that for the single and double quoted tokens it would actually not be necessary to push the character back into the PushbackReader, because the quotes themselves are typically not included as part of the token. For the readSingleTokenWord() however, it is necessary, as the character read is the first character of the token's value.

The implementations of the readDoubleQuotedToken(), readSingleQuotedToken() and readSingleWordToken() have been left out to keep the example short. Just imagine they read a token enclosed by double quotes ("), single quotes (') or a token which ends with a non-word character (e.g. a space, tab, line break etc.).

Jakob Jenkov

Featured Videos

















Sponsored Ads

Maildroppa - Smart Email Marketing Solution
Close TOC

All Trails

Trail TOC

Page TOC

Previous

Next