如何在Java中从控制台读取单个字符(用户键入时)?

如何在Java中从控制台读取单个字符(用户键入时)?,java,input,console,Java,Input,Console,当用户在Java中键入单个字符时,是否有一种简单的方法可以从控制台读取该字符?可能吗?我尝试过这些方法,但它们都在等待用户按enter键: 我开始认为System.in在按下enter键之前不知道用户输入。您要做的是将控制台置于“原始”模式(绕过行编辑,不需要enter键)而不是“煮熟”模式(需要使用enter键进行行编辑)。在UNIX系统上,“stty”命令可以更改模式 现在,关于Java。。。看见摘录: 如果您的程序必须基于控制台, 你必须关掉你的终端 将行模式转换为字符模式,以及 请记住在

当用户在Java中键入单个字符时,是否有一种简单的方法可以从控制台读取该字符?可能吗?我尝试过这些方法,但它们都在等待用户按enter键:


我开始认为System.in在按下enter键之前不知道用户输入。

您要做的是将控制台置于“原始”模式(绕过行编辑,不需要enter键)而不是“煮熟”模式(需要使用enter键进行行编辑)。在UNIX系统上,“stty”命令可以更改模式

现在,关于Java。。。看见摘录:

如果您的程序必须基于控制台, 你必须关掉你的终端 将行模式转换为字符模式,以及 请记住在恢复之前将其恢复 节目结束。没有便携设备 在整个操作系统中实现这一点的方法 系统


建议之一是使用JNI。再说一次,这不是很方便携带。线程末尾的另一个建议,与上面的文章一样,是查看如何使用。

您要做的是将控制台置于“原始”模式(绕过行编辑,不需要输入键)而不是“煮熟”模式(需要输入键进行行编辑)。在UNIX系统上,“stty”命令可以更改模式

现在,关于Java。。。看见摘录:

如果您的程序必须基于控制台, 你必须关掉你的终端 将行模式转换为字符模式,以及 请记住在恢复之前将其恢复 节目结束。没有便携设备 在整个操作系统中实现这一点的方法 系统


建议之一是使用JNI。再说一次,这不是很方便携带。本文末尾的另一个建议,与上面的文章相同,是看看如何使用。

您需要将控制台切换到原始模式。没有内置的独立于平台的方式来实现这一点。不过,这可能很有趣

在Unix系统上,这可能会起作用:

String[] cmd = {"/bin/sh", "-c", "stty raw </dev/tty"};
Runtime.getRuntime().exec(cmd).waitFor();

String[]cmd={”/bin/sh“,“-c”,“sttyraw您需要将控制台切换到raw模式。没有内置的独立于平台的方式。不过,这可能会很有趣

在Unix系统上,这可能会起作用:

String[] cmd = {"/bin/sh", "-c", "stty raw </dev/tty"};
Runtime.getRuntime().exec(cmd).waitFor();

String[]cmd={”/bin/sh“,“-c”,“sttyraw从Java控制台读取原始字符没有可移植的方法


上面已经介绍了一些依赖于平台的解决方法。但要真正实现可移植性,您必须放弃控制台模式,使用窗口模式,例如AWT或Swing。

没有可移植的方法从Java控制台读取原始字符


上面已经介绍了一些依赖于平台的解决方法。但要真正实现可移植性,您必须放弃控制台模式,使用窗口模式,例如AWT或Swing。

我编写了一个Java类,用于调用Windows和Unix/Linux的操作系统函数

  • 在Windows上,它使用msvcrt.dll中的
    \u kbhit()
    \u getwch()
  • 在Unix上,它使用
    tcsetattr()
    将控制台切换到非规范模式,
    System.in.available()
    检查数据是否可用,
    System.in.read()
    从控制台读取字节。
    CharsetDecoder
    用于将字节转换为字符

它支持非阻塞输入以及混合原始模式和普通行模式输入。

我编写了一个Java类,用于调用Windows和Unix/Linux的操作系统函数

  • 在Windows上,它使用msvcrt.dll中的
    \u kbhit()
    \u getwch()
  • 在Unix上,它使用
    tcsetattr()
    将控制台切换到非规范模式,
    System.in.available()
    检查数据是否可用,
    System.in.read()
    从控制台读取字节。
    CharsetDecoder
    用于将字节转换为字符
它支持非阻塞输入、混合原始模式和正常线路模式输入。

使用:

例如:

Terminal terminal = TerminalBuilder.builder()
    .jna(true)
    .system(true)
    .build();

// raw mode means we get keypresses rather than line buffered input
terminal.enterRawMode();
reader = terminal .reader();
...
int read = reader.read();
....
reader.close();
terminal.close();
使用:

例如:

Terminal terminal = TerminalBuilder.builder()
    .jna(true)
    .system(true)
    .build();

// raw mode means we get keypresses rather than line buffered input
terminal.enterRawMode();
reader = terminal .reader();
...
int read = reader.read();
....
reader.close();
terminal.close();

我已经用jcurses做过了

import jcurses.system.InputChar;
import jcurses.system.Toolkit;

//(works best on the local machine when run through screen)
public class readchar3 {
    public static void main (String[] args)
        {
            String st;
            char ch;
            int i;
            st = "";
            ch = ' ';
            i = 0;
            while (true)
                {
                        InputChar c = Toolkit.readCharacter();
                    ch = c.getCharacter();
                    i = (int) ch;
                    System.out.print ("you typed " + ch + "(" + i + ")\n\r");
                    // break on '#'
                    if (ch == '#') break;
                }
            System.out.println ("Programm wird beendet. Verarbeitung kann beginnen.");
        }
}

我已经用jcurses做过了

import jcurses.system.InputChar;
import jcurses.system.Toolkit;

//(works best on the local machine when run through screen)
public class readchar3 {
    public static void main (String[] args)
        {
            String st;
            char ch;
            int i;
            st = "";
            ch = ' ';
            i = 0;
            while (true)
                {
                        InputChar c = Toolkit.readCharacter();
                    ch = c.getCharacter();
                    i = (int) ch;
                    System.out.print ("you typed " + ch + "(" + i + ")\n\r");
                    // break on '#'
                    if (ch == '#') break;
                }
            System.out.println ("Programm wird beendet. Verarbeitung kann beginnen.");
        }
}

JCurses也不是很容易移植……从JCurses自述中可以看出:“JCurses由两部分组成:独立于平台的部分和依赖于平台的部分,后者由本机共享库组成,使原始输入和输出操作可用于第一部分。”@RyanFernandes听起来对我来说是非常可移植的-可以在多个系统上运行的单个工具(使用不同的依赖项)JCurses也不是非常可移植的…从JCurses自述文件:“JCurses由两部分组成:独立于平台的部分和依赖于平台的部分,这两部分由本机共享库组成,使原始输入和输出操作可用于第一部分。”@RyanFernandes听起来对我来说是非常可移植的-单个工具可以在多个系统上运行(使用不同的依赖项)在LinuxWorked下对我很好在Mac上工作。你可能想提到
stty-cook在LinuxWorked下对我也很好在Mac上工作。你可能想提到
stty-cook这个测试/压力测试有多重?@QPaysTaxes压力测试对于控制台输入来说很难。我想,在这种情况下应该是这样的更重要的是在各种环境中测试它(不同的Windows/Linux版本、64/32位、通过SSH的Linux、Telnet、串行端口或桌面控制台等)。到目前为止,我只在我的专用测试工具中使用它。但与其他解决方案(如使用Jansi的JLine2)相比,源代码相对较小我写了它,因为JLine2不支持无阻塞的单字符输入。这就是我所说的压力测试的意思——它可能是一个错误的词;我的坏。总之,很好!我在学校的一个项目中偷了^H^H^H^H^H^H^,它帮了很多忙。嘿-这门课看起来很棒。但是:我不能I don’我不能让它工作。我该如何使用它?我遇到了系统阻塞