aioobe
aioobe

Reputation: 421020

Why can't we read one character at a time from System.in?

The program below prints each character written on standard in, but only after a new-line has been written (at least on my system!).

public class Test {
    public static void main(String[] args) throws java.io.IOException {
        int c;
        while ((c = System.in.read()) != -1)
            System.out.print((char) c);
    }
}

This prevents people from writing stuff like "Press any key to continue" and forces something like "Press enter to continue."

Upvotes: 19

Views: 12188

Answers (3)

hoat4
hoat4

Reputation: 1211

I'm on Ubuntu

Is there a workaround?

Runtime.getRuntime().exec("stty -icanon min 1").waitFor();

And after that all reads of System.in in the same process will read 1 character not waiting for EOL.

Upvotes: 6

Nagaraju Badaeni
Nagaraju Badaeni

Reputation: 900

see my answer in Equivalent function to C's "_getch()" in Java?


public static void getCh() {

final JFrame frame = new JFrame(); synchronized (frame) { frame.setUndecorated(true); frame.getRootPane().setWindowDecorationStyle(JRootPane.FRAME); frame.addKeyListener(new KeyListener() { public void keyPressed(KeyEvent e) { synchronized (frame) { frame.setVisible(false); frame.dispose(); frame.notify(); } } public void keyReleased(KeyEvent e) { } public void keyTyped(KeyEvent e) { } }); frame.setVisible(true); try { frame.wait(); } catch (InterruptedException e1) { } }

}

Upvotes: 0

Lie Ryan
Lie Ryan

Reputation: 64845

What is the underlying reason for this?

Most terminals is line buffered by default, Java does not receive input until a newline.

Is it a limitation of Java?

Some ancient terminals might only have line-buffered input; though it should be possible to disable buffering in most modern terminal.

Is this behavior system-dependent (I'm on Ubuntu)? How does it work on Mac? Windows?

Yes.

Is it dependent on the specific terminal I run the application in? (For me it behaves like this in Eclipse and in gnome-terminal)

Yes.

Is there a workaround?

There are platform specific hacks. curse in Linux and Unix-like platforms, and getch() in Windows. I'm not aware of any cross-platform way.

related: Why "Press any key to continue" is bad idea:

alt text

Upvotes: 19

Related Questions