blog

Home / DeveloperSection / Blogs / Java I/O: The PushbackInputStream Class (Print Calculator Utility)

Java I/O: The PushbackInputStream Class (Print Calculator Utility)

zack mathews 1682 27-May-2016

The PushbackInputStream class comes under the category of FilterInputStream classes. The FilterInputStream has four subclasses. Imagine this class as providing the structure of the pipe for the flow of data. Its subclasses then extract the data into small, usable bits. Out of these four subclasses, we have already used DataInputStream in the previous post. We will use the PushbackInputStream in this post, and the other two later on.

The PushbackInputStream class is used when we want to look ahead in the read buffer to see what the next character is. It creates a one-byte input buffer that allows the input stream to retreat one byte after it has been read, which enables us to test the next byte before taking any action.

The typical application of this comes in lexical analysis of compiler construction. Rather than taking on this traditional example, we will discuss another application that effectively uses this class.

Suppose we are developing a print calculator where the user inputs a number (let’s say the purchase price of an item) on the keypad. If this purchase price contains zero cents, we want to print ** in place of 00 in the item’s price. Thus, if the purchase price is $5.00, the calculator should print $5.**, and if the purchase price is $249.00, it will print $249.**. For any other value after the decimal point, the value is printed “as is.” Thus, the prices $36.02 and $78.85 would be printed as normal. Look at the program here to see how this conversion is done.

import java.io.*;

public class PrintCalc {
                     public static void main(String args[]) {
                             PrintCalc app = new PrintCalc();
                             try {
                                      app.readAndPrint();
                             } catch (IOException e) {
                                      System.out.println("Error encountered during printing");
                             }
                     }
                     private void readAndPrint() throws IOException {
                             PushbackInputStream f = new PushbackInputStream(System.in, 3);
                             int c, c1, c2;
                             while ((c = f.read()) != 'q') {
                                      switch (c) {
                                      case '.':
                                                System.out.print((char) c);
                                                if ((c1 = f.read()) == '0') {
                                                          if ((c2 = f.read()) == '0') {
                                                                   System.out.print("**");
                                                          } else {
                                                                   f.unread(c2);
                                                                   f.unread(c1);
                                                          }
                                                } else {
                                                          f.unread(c1);
                                                }
                                                break;
                                      default:
                                                System.out.print((char) c);
                                                break;
                                      }
                             }
                             f.close();
                     }
}

 

The readAndPrint method reads the number from the keypad, which in our case is the system keyboard, and sends the formatted output to the printer, which in our case is a system console, after making adjustments for zero cents. We first create an instance of PushbackInputStream on the System.in stream:

PushbackInputStream f = new PushbackInputStream(System.in, 3);

The second argument to the constructor sets the buffer size for rollback, which is one byte by default. Therefore, if we use a constructor without the second parameter, we are able to push back only the last read byte.

Next, we set up a loop for reading the keyboard until the user hits the q key on the keypad:

while ((c = f.read()) != 'q') {

We now test the input character for a period (or dot). If the character is not a dot, we print the character on the console in the default case of the switch statement. If a dot is found, we print it on the console and start looking for the “00” character sequence. If this sequence is found, the program prints ** to the console:

if ((c1 = f.read()) == '0') {

            if ((c2 = f.read()) == '0') {
                            System.out.print("**");
 

If some other character follows the first read 0, the program puts both the characters back in the buffer by calling the unread method twice:

  •    f.unread(c2);
  •    f.unread(c1);

If the first read character itself does not equal 0, we simply put it back in the buffer:

else {

f.unread(c1);
}

 

The unread method pushes back a byte by copying it to the front of the pushback buffer. There are other variations (overloaded) of the unread method available that push back a byte array or a portion of a byte array. Please refer to the javadocs to learn about these methods.

Here is some sample output:

$500.00

$500.**
$245.02
$245.02
$549.78
$549.78
$1024.00
$1024.**
$245.0089
$245.**89
q

 

The odd-number lines show the user input and the even-number lines indicate the program generated print number. Note the output for $500.00 and $1024.00, where 00 is replaced with **. The other numbers are printed as is. What about the last input, $245.0089? Here the two zeroes are replaced with the two asterisks. I assume a typical physical calculator would not permit entry beyond two decimal digits.

Also, there is class called PushbackReader that works on character streams, allowing us to push characters back into the stream.


Updated 15-Mar-2018

Leave Comment

Comments

Liked By