8

I am learning JAVA and typed the following DO...WHILE example. The program will quit if I type 'q'. It runs but why I get three rows of "Please a key followed by ENTER:"?

class DWDemo {
    public static void main (String args[])
      throws java.io.IOException {
          char ch;
          do {
              System.out.println("Please a key followed by ENTER:");
              ch = (char) System.in.read();
          } while (ch != 'q');
      }
}

enter image description here

JACKY88
  • 3,391
  • 5
  • 32
  • 48

5 Answers5

10

Because when you type a and hit Enter, then the in.read() method returns three characters - 'a', the character for carriage return \r and the character for line break ('\n'). (Note that the combination \r\n is considered as line-break under Windows).

Your program will have significantly different behavior if you run it under Linux or OSX, because line-breaking character(s) is specific to the OS you're running the program on. Under Linux, it will be \n, under OS X-9 it will be \r, for example.

As a work-around, you can read the whole line (by using a Scanner) and trim it, which will omit the line-breaking character (disregarding the OS type):

public static void main (String args[]) throws java.io.IOException {
      String line;
      Scanner sc = new Scanner(System.in);
      do {
          System.out.println("Please a key followed by ENTER:");
          line = sc.readLine().trim();
      } while (!"q".equals(line));
  }
Konstantin Yovkov
  • 62,134
  • 8
  • 100
  • 147
5

I assume what gets read as input is containing your ENTER keypress. Since you are on Windows, this includes the CRFL line ending.

Thus, each time you entered your char, you actually input 3 chars. For your first input:

  1. a
  2. CR
  3. LF

Try reading a full line via a BufferedReader and run a whitespace trim on that, or just evaluate its first char.

kasoban
  • 2,107
  • 17
  • 24
3

When typing input on a command line on a Windows system, all lines are ended in a line feed consisting of the characters \r\n. So when you type a that first time, you are actually typing a\r\n.

When the code System.in.read() is run, it reads just the first character that has been entered into the buffer, in this case a. Then the loop runs, prints out your prompt and tries to read the next character on the buffer. In this case the \r\n is still on the buffer so it reads in \r. Loops again and it reads in \n. Finally it prints the prompt a third time since the buffer is empty, it waits for your input.

In order to avoid this I would suggest using a different method to read in from the command line instead of System.In. Perhaps the Scanner class would be more appropriate.

Evan Frisch
  • 1,334
  • 5
  • 22
  • 40
  • This is almost correct, except that read doesn't return characters; it returns bytes. If you enter a non-ASCII character, it will probably return two consecutive values depending on the default encoding. – Klitos Kyriacou Nov 11 '15 at 13:39
1

One thing you have to be aware of is that System.in.read() only takes in 1 byte of input. See doc here. So when you enter a character a, that is already one byte, by entering an additional ENTER key, characters: \r and \n, that will be captured by the read() two more times, which triggers additional loop iteration and print logic.

Jeff Dale
  • 76
  • 3
0

As @kasoban said they are a ,CR and LF. It is repeating 3 times, but it will change according to the OS. So I advise you to use a Scanner. You can find sample below

public class DW {
    public static void main (String args[]) throws java.io.IOException {
      String s;
      Scanner scanner = new Scanner(System.in);
      do {
          System.out.println("Please a key followed by ENTER:");
          s = scanner.nextLine();
        } while (!"q".equals(s));
      }
    }
Seray Uzgur
  • 113
  • 7