Як прочитати один конверт з консолі Java (як користувач вводить його)?


110

Чи є простий спосіб прочитати одну конфігурацію з консолі, коли користувач набирає її на 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 не знає введення користувача, поки не буде натиснуто Enter .

Відповіді:


57

Що ви хочете зробити, це перевести консоль в "сировинний" режим (редагування рядків обходить і не потрібно вводити клавішу введення) на відміну від "приготовленого" режиму (редагування рядків за допомогою клавіші введення.) У системах UNIX команда 'stty' може зміни режимів.

Тепер щодо Java ... див. Неблокуючі введення консолі в Python та Java . Витяг:

Якщо ваша програма повинна базуватися на консолі, вам доведеться перевести свій термінал з лінійного режиму в режим символів, і не забудьте відновити його до завершення програми. Немає портативного способу зробити це в операційних системах.

Однією з пропозицій є використання JNI. Знову ж таки, це не дуже портативно. Ще одна пропозиція в кінці нитки, і спільна з публікацією вище, полягає в тому, щоб подивитися на використання jCurses .


4
JCurses теж не дуже портативний .... Із JCurses ЧИТАЙТЕ: "JCurses складається з двох частин: незалежної від платформи форми та залежної від платформи форми, яка складається з натурної спільної бібліотеки, яка робить первісні операції введення та виведення доступними до першої частини . "
Райан Фернандес

6
@RyanFernandes звучить для мене досить портативно - єдиний інструмент, який можна запустити в декількох системах (з використанням різних залежностей)
Antoniossss

25

Потрібно перебити консоль у сирому режимі. Не існує вбудованої платформи незалежної можливості дістатися туди. jCurses, можливо, буде цікаво.

У системі Unix це може працювати:

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

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



4
Працював і на Mac. Ви, мабуть, хочете згадати, що stty cooked </dev/ttyслід запустити, коли програмі потрібно повернутися до буферизованого режиму, і обов'язково перед виходом програми.
Келвін

15

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

Деякі способи, залежні від платформи, були представлені вище. Але щоб бути справді портативним, вам доведеться відмовитися від консольного режиму та використовувати режим вікон, наприклад AWT або Swing.


22
Я не зовсім розумію, чому, наприклад, Mono (або CLR) System.Console.ReadKeyпрацює з усіма платформами. Java також поширює JVM та JRE для кожної платформи з залежними від платформи бібліотеками та реалізаціями, так що це не привід.
Мартін Мачак

13

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

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

Він підтримує неблокуючий вхід та змішування вихідного режиму та звичайний вхідний режим.


Наскільки сильно це було перевірено / перевірено на стрес?
Фонд позову Моніки

2
@QPaysTaxes Стрес-тестування важко для введення консолі. Я думаю, що в цьому випадку було б важливіше протестувати його в різних середовищах (різні версії Windows / Linux, 64/32 біт, Linux через SSH, Telnet, послідовний порт або консоль робочого столу тощо). Поки я використовую його лише в своїх приватних інструментах тестування. Але вихідний код порівняно з іншими рішеннями (наприклад, JLine2, який використовує Jansi) порівняно невеликий. Тож не так багато може піти не так. Я написав це, тому що JLine2 не підтримує введення одного символу без блокування.
Крістіан д'Евреузе

Це те, що я мав на увазі під тестом на стрес - це, мабуть, неправильне слово; моє ліжко. У всякому разі, приємно! Я вкрав ^ H ^ H ^ H ^ H ^ H ^ Співав це в моєму проекті для школи, і це допомогло купу.
Фонд позову Моніки

Гей - цей клас виглядає чудово. Однак: я не можу змусити його працювати .. як я повинен ним користуватися? Я стикався з блокуванням System.in, поки не натискав CTRL + D (на Linux) і тепер читав про консольні режими та подібні. Я думаю, що ваш RawConsoleInput - це те, що я шукаю - але як це використовувати?
Ігор

@Igor Просто зателефонуйте на RawConsoleInput.read (булева), щоб прочитати символ клавіатури. Це задокументовано у вихідному коді (RawConsoleInput.java).
Крістіан d'Heureuse

8

Використовуйте 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; однак це працює чудово.
RawToast

jline має практично все, що потрібно для створення інтерактивної консолі / термінальної системи. Він чудово працює в Linux. Більш повний приклад дивіться на: github.com/jline/jline3/blob/master/builtins/src/test/java/org/… . У ньому є автозаповнення, історія, маска пароля тощо
lepe
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.