Java Interactive I-O

Nicholas Duchon: Oct 4, 2015.

Outline


Java 1.5 style - Simple:

Java interactive I/O is a little complicated, and there are a number of ways to get user input and send output to the screen. Let me list a few ways:

Input:

  1. new Scanner (System.in)
  2. TextField and TextArea from awt
  3. JTextField and JTextArea from swing classes
  4. JOptionPane also from swing classes

Most of these return a String, so the next task to parse the string. The most obvious choice is StringTokenizer or String.split.

Output:

  1. System.out.print, System.out.println, System.out.printf
  2. TextField and TextArea from awt
  3. JTextField and JTextArea from swing classes
  4. JOptionPane also from swing

For a general reference, I suggest that some of you post examples of applications and/or applets that use one of these classes.

Code:

From the user's view, a nice program interface is one that accepts lots of input on a single line, and uses some kind of flag value on that same line to quit. The default should be to continue unless the flag value is entered. Errors should be reported without causing a program crash, and letting the user try again.

What are good ways to go about this in languages similar to Java? Here are a few approaches. Let me start with my recommendation, and then consider some simpler alternatives and point out why they have issues.

Recommended:

Use a boolean function thus:


public static void main (String args []) {
  Scanner scr = new Scanner (System.in);
  while (menu(scr));
  System.out.println ("--- Bye.");
} //
end main


public static boolean menu (Scanner sc) {
  System.out.print ("Prompt, q to quit: ");
  String inline = sc.nextLine ();
  if (inline.equals ("q")) return false;
  // do stuff with input line
  return true;
} //
end menu

Tokenizing:

Tokenizing the input line - "\\s+" compresses white space, use  "\\s*:\\s*" to split on colons ignoring white space, for example. (+ is one or more characters, * is 0 or more characters of that type.)


static boolean menu (Scanner sc) {
   System.out.print ("Command, [q or Q to quit]: ");
   Scanner tokens = new Scanner (sc.nextLine()).useDelimiter ("\\s+");
   while (tokens.hasNext()) {
      String st = tokens.next();
      if (st.equalsIgnoreCase ("q"))
         return false;
      else
         System.out.printf ("token >%s<\n", st);
   } // end for each token
   return true;
 } //
end method menu

Alternatives:

  1. /* prompt for and get input */
    while (! input.equals "q") {
      /* do stuff */
    /* prompt for and get input */ }

  2. /* prompt for and get input */
    do {
      /* do stuff */
      /* prompt for and get input */
    } while (! input.equals ("q"));

  3. while (true) {
      /* prompt for and get input */
      if (input.equals ("q")) break;
      /* do stuff */
    } // end while

Issues:

  1. Requires input to be initialized to something before the loop starts, perhaps with an initial prompt/input cycle. It can be annoying to make sure the prompt/input cycle inside the loop matches the cycle before the loop, and repeating code like this is just not pretty.
  2. The input will not actually stop the loop until the end of the "do stuff" part of the loop. Typically this means another test inside the loop to skip over stuff if the user wants to quit, or that the user will have to go through at least one real example before they are allowed to quit, which is annoying. And again we have the issue of two prompt/input cycles.
  3. I find this more appealing since the code loop can exit at any point, but this does not seem as clean as the while loop in the recommended version. The code in (3) attempts to both handle the exit case and the general case in the same place, which can be confusing and more complex than the recommendation.
  4. Recommended code: The menu method also makes it easier to flag errors without having complex and nested else conditions. If something goes wrong, but the program should continue, just return true immediately, and only fall through if the input is acceptable so far, for example.

ND.