Home > database >  How to ignore input from `BufferedReader` when using `Thread.sleep()`?
How to ignore input from `BufferedReader` when using `Thread.sleep()`?

Time:04-29

I'm trying to make a simple counter that starts between user inputs (3..., 2..., 1..., Go!).

try (var reader = new BufferedReader(new InputStreamReader(System.in))) {
    ...
    try {
        for (int i = 0; i < 3; i  ) {
            System.out.println(i   "...");
            Thread.sleep(500);
        }
        System.out.println("Go!");
    } catch (Exception e) {
        e.printStackTrace();
    }
    ...
}

The problem is Im still able to press keys between delays, which then gets printed. Is there a way to block BufferedReader while for-each works?

CodePudding user response:

You cannot prevent the user pressing keys while he should be waiting. For the same reason you cannot prevent your application to receive these characters through System.in up until the BufferedReader. Blocking that is the wrong approach.

What you can do however is ignore those keypresses. But you must prevent that they remain in the input buffer and get evaluated after your loop.

Since you are reading from stdin however, it is not your program to print the characters. I guess it is the terminal emulator that you use when running your console based application. And therefore I am unsure how you can prevent the echo to the console. What undermines my assumption is https://forums.codeguru.com/showthread.php?466009-Reading-from-stdin-(without-echo)

What proves I am wrong (and what you should try out therefore) is How to use Scanner to read silently from STDIN in Java? or more general https://www.geeksforgeeks.org/ways-to-read-input-from-console-in-java/

Both recommend to suppress the echo by reading from System.console().

CodePudding user response:

Your problem is not related to the BufferedReader, and the solution is probably more complex than what you imagined.

When you run your Java process, it is usually connected to a terminal. This terminal (or emulator) handles your keyboard and usually provides your input line by line to the attached process. The terminal also echos characters as you type. Meaning the Java process does not print the characters you type, you therefor can't prevent them being printed from within the your process.

Terminals and terminal control is highly platform specific. On Linux system you can control the terminal using termios. The flags you want to be disable is ECHO for echoing your keystrokes and ICANON to disable canonical mode so you'd receive input as soon as it is available. You'd have to perform this before your loop. After or in your loop you'd have to consume any input and discard it, enable ECHO and ICANON again. Be aware though that the BufferedReader might have something buffered already and is performing blocking I/O.

termios however is not directly accessible from Java, calls would have to be wrapped through JNI f.i. A quick google search came up with a library called purejavacomm

  • Related