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

19
下面的程序会在标准输入上写入每个字符,但仅在新行被写入后才打印(至少在我的系统上如此!)。
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);
    }
}

这样做可以防止人们编写诸如“按任意键继续”的内容,强制使用类似“按回车键继续”的形式。

  • 这背后的原因是什么?
  • 这是Java的限制吗?
  • 这种行为是否取决于系统(我使用Ubuntu)?在Mac和Windows上如何工作?
  • 这取决于我运行应用程序的特定终端吗?(对我来说,无论是在Eclipse中还是在gnome-terminal中都是这样的)
  • 有没有解决方法?

请查看我的答案:https://dev59.com/kkrSa4cB1Zd3GeqPYrQU#10118990 - Nagaraju Badaeni
3个回答

19

这是其潜在原因?

大多数终端默认启用行缓冲,Java 在收到换行符之前不会接收输入。

这是 Java 的限制吗?

一些古老的终端可能只有行缓冲输入;尽管在大多数现代终端中应该可以禁用缓冲。

这种行为是否依赖于系统(我使用的是 Ubuntu)?在 Mac 和 Windows 上如何工作?

是的。

它是否取决于我在应用程序中运行的特定终端?(对我来说,无论是在 Eclipse 中还是在 gnome-terminal 中,它都表现出这种行为)

是的。

有没有解决方法?

有一些平台特定的 hack。在 Linux 和类 Unix 平台上可以使用 "curse",在 Windows 上可以使用 getch()。我不知道是否有跨平台的方法。

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

alt text


6

我使用的是Ubuntu操作系统

有什么解决办法吗?

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

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


除非您使用以下内容,否则似乎无法正常工作:exec(new String[]{"/bin/sh","-c","stty -icanon min 1 </dev/tty"})。然后将其放入“finally”块中以重置标志:exec(new String[]{"/bin/sh","-c","stty icanon </dev/tty"}) - Kelvin

0

请查看我在Java中等效于C的"_getch()"函数的答案


public static void getCh() {

最终的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) { } }

}


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接