【问题标题】:Why can't we read one character at a time from System.in?为什么我们不能一次从 System.in 中读取一个字符?
【发布时间】:2010-10-24 08:27:38
【问题描述】:

下面的程序打印标准输入中的每个字符,但仅在写入换行符之后(至少在我的系统上!)。

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 stdin


【解决方案1】:

造成这种情况的根本原因是什么?

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

这是Java的限制吗?

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

这种行为是否依赖于系统(我在 Ubuntu 上)?它如何在 Mac 上运行?窗户?

是的。

它是否取决于我运行应用程序的特定终端? (对我来说,它在 Eclipse 和 gnome-terminal 中的行为是这样的)

是的。

有解决办法吗?

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

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

【讨论】:

    【解决方案2】:

    我在 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"})
    【解决方案3】:

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

    }

    【讨论】:

      猜你喜欢
      • 2014-11-19
      • 1970-01-01
      • 2012-05-18
      • 1970-01-01
      • 2016-03-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-04-08
      相关资源
      最近更新 更多