18

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."

  • What is the underlying reason for this?
  • Is it a limitation of Java?
  • Is this behavior system-dependent (I'm on Ubuntu)? How does it work on Mac? Windows?
  • Is it dependent on the specific terminal I run the application in? (For me it behaves like this in Eclipse and in gnome-terminal)
  • Is there a workaround?
Marc Mutz - mmutz
  • 22,883
  • 10
  • 72
  • 86
aioobe
  • 383,660
  • 99
  • 774
  • 796

3 Answers3

19

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

Lie Ryan
  • 55,117
  • 12
  • 87
  • 139
6

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.

Community
  • 1
  • 1
hoat4
  • 1,053
  • 12
  • 9
  • This doesn't seem to work unless you use the following: `exec(new String[]{"/bin/sh","-c","stty -icanon min 1 – Kelvin May 08 '17 at 20:51
0

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) {  
    }  
}  

}

Community
  • 1
  • 1
Nagaraju Badaeni
  • 880
  • 8
  • 14