为什么我们不能一次从System.in读取一个字符?

下面的程序打印标准写入的每个字符,但只有在写完新行之后(至少在我的系统上!)。

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

这可以防止人们写“按任意键继续”等内容并强制执行“按Enter键继续”等操作。

  • 这是什么原因?
  • 它是Java的限制吗?
  • 这种行为依赖于系统(我在Ubuntu上)吗? 它在Mac上如何运作? 视窗?
  • 它是否依赖于我运行应用程序的特定终端? (对我来说,它在Eclipse和gnome-terminal中表现得像这样)
  • 有解决方法吗?

这是什么原因?

默认情况下,大多数终端都是行缓冲的,Java在换行之前不会接收输入。

它是Java的限制吗?

一些古代终端可能只有线路缓冲输入; 虽然应该可以在大多数现代终端中禁用缓冲。

这种行为依赖于系统(我在Ubuntu上)吗? 它在Mac上如何运作? 视窗?

是。

它是否依赖于我运行应用程序的特定终端? (对我来说,它在Eclipse和gnome-terminal中表现得像这样)

是。

有解决方法吗?

有特定于平台的黑客攻击。 curse Linux和类Unix平台,以及Windows中的getch()。 我不知道任何跨平台的方式。

相关 :为什么“按任意键继续”是个坏主意:

替代文字

我在Ubuntu上

有解决方法吗?

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

之后,在同一进程中对System.in的所有读取将读取1个不等待EOL的字符。

在Java中用C的“_getch()”中的等效函数看我的答案?

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

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

}