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

Enter 를 누를 때까지 System.in이 사용자 입력을 인식하지 못한다고 생각하기 시작했습니다 .

답변:


57

원하는 것은 "cooked"모드 (Enter 키가 필요한 라인 편집)와는 반대로 콘솔을 "raw"모드 (라인 편집 생략 및 Enter 키 필요 없음)로 설정하는 것입니다. UNIX 시스템에서 'stty'명령은 다음을 수행 할 수 있습니다. 모드를 변경하십시오.

이제 Java와 관련하여 ... Python 및 Java의 Non blocking console input을 참조하십시오 . 발췌 :

프로그램이 콘솔 기반이어야하는 경우 터미널을 라인 모드에서 문자 모드로 전환해야하며 프로그램이 종료되기 전에 복원해야합니다. 운영 체제간에이를 수행 할 수있는 이식 가능한 방법은 없습니다.

제안 중 하나는 JNI를 사용하는 것입니다. 다시 말하지만, 그것은 그다지 이식성이 없습니다. 스레드 끝에서 그리고 위의 게시물과 공통적으로 다른 제안은 jCurses 사용을 살펴 보는 입니다.


4
JCurses는 이식성이 매우 낮습니다 .... JCurses README에서 : "JCurses는 두 부분으로 구성됩니다. 첫 번째 부분에서 기본 입력 및 출력 작업을 사용할 수 있도록하는 기본 공유 라이브러리로 구성된 플랫폼 독립 부분과 플랫폼 종속 부분입니다. . "
Ryan Fernandes

6
@RyanFernandes는 나에게 상당히 이식성이있는 것처럼 들립니다. 여러 시스템에서 실행할 수있는 단일 도구 (다른 종속성 사용)
Antoniossss

25

콘솔을 원시 모드로 두어야합니다. 플랫폼에 독립적 인 기본 제공 방법은 없습니다. 하지만 jCurses흥미로울 수 있습니다.

Unix 시스템에서는 다음과 같이 작동 할 수 있습니다.

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

예를 들어, 키 입력 사이의 시간을 고려하려는 경우 여기에 도달 할 수있는 샘플 코드가 있습니다.


Linux에서 나를 위해 잘 작동했습니다
MrSmith42

4
Mac에서도 작동했습니다. stty cooked </dev/tty프로그램이 버퍼 모드로 되돌려 야 할 때 그리고 확실히 프로그램이 종료되기 전에 실행되어야한다고 언급하고 싶을 것입니다 .
Kelvin

15

Java 콘솔에서 원시 문자를 읽을 수있는 이식 가능한 방법은 없습니다.

위에 제시된 일부 플랫폼에 따른 해결 방법이 있습니다. 그러나 정말 휴대하기 위해서는 콘솔 모드를 포기하고 AWT 또는 Swing과 같은 윈도우 모드를 사용해야합니다.


22
예를 들어 Mono (또는 CLR)가 System.Console.ReadKey모든 플랫폼에서 작동 하는 이유를 이해하지 못합니다 . Java는 또한 플랫폼 종속 라이브러리 및 구현이있는 모든 플랫폼에 JVM 및 JRE를 배포하므로 변명의 여지가 없습니다.
Martin

13

JNA 를 사용 하여 Windows 및 Unix / Linux의 운영 체제 기능을 호출 하는 Java 클래스 RawConsoleInput 을 작성했습니다 .

  • Windows의 경우는 사용 _kbhit()_getwch()MSVCRT.DLL에서.
  • Unix에서는 tcsetattr()콘솔을 비표준 모드로 전환하고 System.in.available()데이터를 사용할 수 있는지 확인 System.in.read()하고 콘솔에서 바이트를 읽는 데 사용합니다. A CharsetDecoder는 바이트를 문자로 변환하는 데 사용됩니다.

Non-blocking 입력과 혼합 raw 모드와 일반 라인 모드 입력을 지원합니다.


얼마나 많이 테스트 / 스트레스 테스트를 거쳤습니까?
기금 모니카의 소송

2
@QPaysTaxes 콘솔 입력에 대한 스트레스 테스트는 어렵습니다. 이 경우 다양한 환경 (다른 Windows / Linux 버전, 64/32 비트, SSH를 통한 Linux, Telnet, 직렬 포트 또는 데스크톱 콘솔 등)에서 테스트하는 것이 더 중요하다고 생각합니다. 지금까지는 개인 테스트 도구에서만 사용했습니다. 그러나 소스 코드는 다른 솔루션 (Jansi를 사용하는 JLine2와 같은)에 비해 상대적으로 작습니다. 따라서 잘못 될 수있는 것은 많지 않습니다. JLine2는 차단없이 단일 문자 입력을 지원하지 않기 때문에 작성했습니다.
Christian d' Heureuse

이것이 제가 스트레스 테스트에서 의미하는 바입니다. 아마도 잘못된 단어 일 것입니다. 내 잘못이야. 어쨌든 좋아요! 저는 학교 프로젝트에서 ^ H ^ H ^ H ^ H ^ H ^을 훔 쳤고 많은 도움이되었습니다.
기금 모니카의 소송

헤이-이 수업은 멋져 보입니다. 그러나 : 작동하도록 할 수 없습니다. 어떻게 사용해야합니까? 나는 CTRL + D (Linux)를 누를 때까지 System.in 블로킹을 만났고 이제 콘솔 모드 등을 읽었습니다. RawConsoleInput이 내가 찾고있는 것이라고 생각하지만 어떻게 사용합니까?
이고르

@Igor 키보드 문자를 읽으려면 RawConsoleInput.read (boolean)를 호출하십시오. 소스 코드 (RawConsoleInput.java)에 문서화되어 있습니다.
Christian 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/…를 참조하십시오 . 그것은 자동 완성, 역사, 암호 마스크 등이있다
레페
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.