Как прочитать один символ с консоли на Java (как пользователь его вводит)?

Есть ли простой способ прочитать один символ из консоли, когда пользователь печатает его на Java? Является ли это возможным? Я пробовал с этими методами, но все они ждут, пока пользователь нажмет клавишу ввода:

char tmp = (char) System.in.read();
char tmp = (char) new InputStreamReader(System.in).read ();
char tmp = (char) System.console().reader().read();           // Java 6

Я начинаю думать, что System.in не знает о пользовательском вводе, пока не будет нажата кнопка ввода.

7 ответов

Решение

То, что вы хотите сделать, это перевести консоль в "сырой" режим (обведение строки обойдено и ключ ввода не требуется), в отличие от "готового" режима (редактирование строки с ключом ввода.) В системах UNIX команда 'stty' может смена режимов.

Теперь относительно Java... см. Неблокирующая консольная запись в Python и Java. Выдержка:

Если ваша программа должна быть основана на консоли, вы должны переключить свой терминал из линейного режима в символьный режим, и не забудьте восстановить его до выхода из программы. Нет переносимого способа сделать это в операционных системах.

Одним из предложений является использование JNI. Опять же, это не очень портативно. Еще одно предложение в конце ветки, как и в предыдущем посте, заключается в использовании jCurses.

Вам нужно перевести вашу консоль в сырой режим. Нет встроенного независимого от платформы способа добраться туда. Хотя курсы могут быть интересными.

В системе Unix это может работать:

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

Например, если вы хотите учесть время между нажатиями клавиш, вот пример кода, чтобы добраться туда.

Я написал Java-класс RawConsoleInput, который использует JNA для вызова функций операционной системы Windows и Unix/Linux.

  • На Windows это использует _kbhit() а также _getwch() из msvcrt.dll.
  • На Unix он использует tcsetattr() переключить консоль в неканонический режим, System.in.available() проверить, доступны ли данные и System.in.read() читать байты из консоли. CharsetDecoder используется для преобразования байтов в символы.

Он поддерживает неблокирующий ввод и смешивание исходного режима и нормального ввода в линейном режиме.

Не существует переносимого способа чтения необработанных символов с консоли Java.

Некоторые зависящие от платформы обходные пути были представлены выше. Но чтобы быть действительно переносимым, вам придется отказаться от консольного режима и использовать оконный режим, например AWT или Swing.

Используйте jline3:

Пример:

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

Видеть это

Он вызывает функцию _getch() из c для чтения одного символа без нажатия Enter.

Другие вопросы по тегам