Вопрос по console, input, java – Как прочитать один символ из консоли на Java (как пользователь его вводит)?

96

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

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 не знает о вводе пользователя, покаenter нажата.

Ваш Ответ

5   ответов
14

нсоли Java.

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

Я не совсем понимаю, почему, например, Mono (или CLR) имеетSystem.Console.ReadKey который работает на всех платформах. Java также распространяет JVM и JRE для каждой платформы с зависимыми от платформы библиотеками и реализациями, так что это не оправдание.
5

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();
Я обнаружил, что решения на основе RawConsoleInput не работают на MacOS High Sierra; Однако это работает отлично.
В jline есть практически все, что вам нужно для создания интерактивной консоли / терминальной системы. Отлично работает в Linux. Для более полного примера посмотрите на:github.com/jline/jline3/blob/master/builtins/src/test/java/org/… , Имеет автозаполнение, историю, маску пароля и т. Д.
11

RawConsoleInput который используетЮНА вызывать функции операционной системы Windows и Unix / Linux.

On Windows it uses _kbhit() and _getwch() from msvcrt.dll. On Unix it uses tcsetattr() to switch the console to non-canonical mode, System.in.available() to check whether data is available and System.in.read() to read bytes from the console. A CharsetDecoder is used to convert bytes to characters.

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

@Igor Просто вызовите RawConsoleInput.read (логическое значение), чтобы прочитать символ клавиатуры. Это задокументировано в исходном коде (RawConsoleInput.java).
Насколько сильно это было проверено / подвергнуто стресс-тестированию?
Эй, этот класс выглядит великолепно. Однако: я не могу заставить его работать .. как я должен его использовать? Я сталкивался с блокировкой System.in, пока не нажал CTRL + D (в Linux), и теперь я читаю о режимах консоли и тому подобном. Я думаю, что ваш RawConsoleInput - это то, что я ищу, но как мне его использовать?
@QPaysTaxes Стресс-тестирование сложно для ввода с консоли. Я думаю, в этом случае было бы более важно протестировать его в различных средах (разные версии Windows / Linux, 64/32 бит, Linux через SSH, Telnet, последовательный порт или консоль рабочего стола и т. Д.). Пока я использую его только в своих личных инструментах тестирования. Но исходный код относительно невелик по сравнению с другими решениями (например, JLine2, в котором используется Jansi). Так что мало что может пойти не так. Я написал это, потому что JLine2 не поддерживает ввод одного символа без блокировки.
56

raw & quot; режим (редактирование строки пропущено и клавиша ввода не требуется), а не "готовый" режим (требуется редактирование строки с помощью клавиши ввода). В системах UNIX параметр 'stty' Команда может менять режимы.

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

If your program must be console based, you have to switch your terminal out of line mode into character mode, and remember to restore it before your program quits. There is no portable way to do this across operating systems.

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

JCurses также не очень переносим .... Из JCurses README: «JCurses состоит из двух частей: независимой от платформы части и зависимой от платформы части, которая состоит из собственной общей библиотеки, делающей примитивные операции ввода и вывода доступными для первой часть & Quot.
@RyanFernandes звучит довольно портативно для меня - один инструмент, который можно запускать на нескольких системах (используя разные зависимости)
22

от платформы способа добраться туда.Хотя курсы могут быть интересными.

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

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

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

Работал и на Mac. Вы, вероятно, хотите упомянуть, чтоstty cooked </dev/tty должен быть запущен, когда программе необходимо вернуться в буферный режим, и определенно до выхода из программы.
& Quot; Например ... & quot; ссылка сейчас мертва
У меня нормально работало под линуксом

Похожие вопросы