Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: separated into CS

...

Create and use only a single BufferedInputStream on System.in. This compliant solution declares the BufferedInputStream as a class variable so that all methods can access it. However, if a program were to use this library in conjunction with other input from a user that needs another buffered wrapper on System.in, the library must be modified so that all code uses the same buffered wrapper instead of additional ones that are created.

Code Block
bgColor#ccccff
public final class InputLibrary {
  private static BufferedInputStream in = new BufferedInputStream(System.in);

  public static char getChar() throws EOFException {
    int input = in.read();
    if (input == -1) {
      throw new EOFException();
    }
    in.skip(1); // This statement is now necessary to go to the next line
                // The noncompliant code example deceptively worked without it
    return (char)input; 
  }

  public static void main(String[] args) {
    try {
      System.out.print("Enter first initial: ");
      char first = getChar();
      System.out.println("Your first initial is " + first);
      System.out.print("Enter last initial: ");
      char last = getChar();
      System.out.println("Your last initial is " + last);
    } catch(EOFException e) {
        System.out.println("ERROR");
    }
  }
}

...

This program was compiled with the command javac InputLibrary.java on a system with Java 1.6.0. When run from the command line with java InputLibrary, the program successfully takes two characters as input and prints them out. Also, when run with java InputLibrary < input, where input is a file that contains the exact same input, the program successfully takes two characters as input and print them out.

Compliant Solution

If a program intends to use the library InputLibrary in conjunction with other code that requires user input and consequently needs another buffered wrapper around System.in, its code must use the same buffered wrapper as the one used by the library, instead of creating and using an additional buffered wrapper. The library InputLibrary must return an instance of the buffered wrapper to support this functionality.

Code Block
bgColor#ccccff

public final class InputLibrary {
  private static BufferedInputStream in = new BufferedInputStream(System.in);

  // Other methods

  static BufferedInputStream getBufferedWrapper() {
    return in;
  }
}

// Some code that requires user input from System.in
class AppCode {
  private static BufferedInputStream in;
  
  AppCode() {
    in =  InputLibrary.getBufferedWrapper();
  }
  // Other methods
}

Note that this scheme may not work very well in multi-threaded environments because by default, reading from a stream is not a thread-safe operation. Explicit synchronization is required in such cases.

Risk Assessment

Creating multiple buffered wrappers around an InputStream can cause unexpected program behavior when the InputStream is re-directed.

...