18

I am creating a simply story, which will occasionally prompt the user to hit ENTER. It works the first time I prompt for it, but then it will immediately execute the other prompts, maybe because the program runs so fast by the time you let the ENTER key up, it already ran the check for the prompts.

Any ideas? Code Below.

    System.out.println("...*You wake up*...");
    System.out.println("You are in class... you must have fallen asleep.");
    System.out.println("But where is everybody?\n");
    promptEnterKey();

    System.out.println("You look around and see writing on the chalkboard that says CBT 162");
    promptEnterKey();

//////////////////////////////////////////////////////

public void promptEnterKey(){
    System.out.println("Press \"ENTER\" to continue...");
    try {
        System.in.read();
    } catch (IOException e) {
        e.printStackTrace();
    }
}
MasonAlt
  • 329
  • 2
  • 3
  • 12
  • 3
    I think you need to use the scanner class – Kiraged Oct 03 '14 at 18:16
  • 1
    take a look at [this SO post](http://stackoverflow.com/questions/7877529/java-string-scanner-input-does-not-wait-for-info-moves-directly-to-next-stateme)... Please read other questions before reposing the same thing – starvator Oct 03 '14 at 18:17
  • 3
    In the future, you can also `System.out.print(System.in.read());` to see what's going on. [This Ascii table](http://www.asciitable.com/) points out that a carriage return and newline are being read off the in. – Compass Oct 03 '14 at 18:24

2 Answers2

28

The reason why System.in.read is not blocking the second time is that when the user presses ENTER the first time, two bytes will be stored corresponding to \r and \n.

Instead use a Scanner instance:

public void promptEnterKey(){
   System.out.println("Press \"ENTER\" to continue...");
   Scanner scanner = new Scanner(System.in);
   scanner.nextLine();
}
M A
  • 65,721
  • 13
  • 123
  • 159
  • 1
    Don't use scanner because you are not actually using the input. Look at my solution below...it is better cause you do not need the input. – brso05 Oct 03 '14 at 18:21
  • The input doesn't have to be used. Garbage can be entered on the line in a worst-case scenario and it will not have effect on the program once the expected /r/n input is performed. – Compass Oct 03 '14 at 18:23
  • 1
    @brso05 - They're both valid solutions. – Krease Oct 03 '14 at 18:23
  • True but you are initializing a Scanner object when you don't need it it is not effficient its a waste. – brso05 Oct 03 '14 at 18:23
  • 8
    @brso05 - we get it. You posted an alternative answer. Trying to oversell it will not get you positive attention. – Krease Oct 03 '14 at 18:27
  • It's not overselling as a programmer you should try to be as efficient as possible if you start bad habits they will probably continue and get worse – brso05 Oct 03 '14 at 18:29
  • 2
    I feel like this addresses the issue. Program execution will **ONLY** continue when `Enter` is pressed, and not when I slam my forehead into the keyboard and fill the buffer with `ADSFOJASD`. The alternative is to keep peeking at the System.in stack until you get the newline. – Compass Oct 03 '14 at 18:29
  • You shouldn't use something because it works you should use it because its the best solution to your problem – brso05 Oct 03 '14 at 18:29
  • @brso05 If the user enters ABC then presses Enter on the first prompt, will he or she be able to hit Enter on the second prompt? If no then your approach does not solve the OP's problem. – M A Oct 03 '14 at 18:31
  • 1
    I am using the Scanner class already to obtain other input from the user. I didn't know about the .nextLine() as .next() doesn't work without entering some sort of data. – MasonAlt Oct 03 '14 at 18:39
  • And I will be using the Scanner option because it's easier to implement for `Enter`-only input. In this manner, it is the best solution. – Andrew Aug 25 '17 at 19:28
  • This doesn't seem to work. It just moves on without waiting for an `Enter`. What's happening and how can I fix it? – Voldemort's Wrath Jul 15 '19 at 00:57
7

If we keep your approach of using System.in, the right thing to do is defining the bytes you will want to read, change your prompEnterKey to this:

   public static void promptEnterKey(){
        System.out.println("Press \"ENTER\" to continue...");
        try {
            int read = System.in.read(new byte[2]);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

It will work as you need. But, as the others said, you can try different approaches like the Scanner class, that choice is up to you.

Community
  • 1
  • 1
Bruno Franco
  • 1,958
  • 8
  • 20
  • 4
    If we're going with the System.in, we shouldn't allow it to continue unless `/r/n` is read off the stack. Else pressing random keys will result in code continuing when it shouldn't, per spec. – Compass Oct 03 '14 at 18:27
  • 4
    Yeah, you got a point, for a safer situation, he needs to vadidate this possible entries. – Bruno Franco Oct 03 '14 at 18:31