Como ler um único char do console em Java (como o usuário digita)?

Existe uma maneira fácil de ler um único caractere do console quando o usuário o digita em Java? É possível? Eu tentei com esses methods, mas todos eles esperam que o usuário pressione a tecla enter :

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

Estou começando a pensar que o System.in não está ciente da input do usuário até que o enter seja pressionado.

O que você quer fazer é colocar o console em modo “raw” (edição de linha ignorada e sem necessidade de inserir chave) em oposição ao modo “cozido” (edição de linha com a tecla enter necessária). Nos sistemas UNIX, o comando ‘stty’ pode mudar modos.

Agora, com relação ao Java … veja Entrada do console sem bloqueio em Python e Java . Excerto:

Se o seu programa precisa ser baseado em console, você precisa mudar o modo de terminal para fora do modo de linha, e lembre-se de restaurá-lo antes que o programa saia. Não existe uma maneira portátil de fazer isso nos sistemas operacionais.

Uma das sugestões é usar o JNI. Mais uma vez, isso não é muito portátil. Outra sugestão no final do tópico, e em comum com o post acima, é examinar o uso do jCurses .

Você precisa derrubar seu console no modo raw. Não há uma maneira integrada independente de plataforma de chegar lá. jCurses pode ser interessante, no entanto.

Em um sistema unix, isso pode funcionar:

  String[] cmd = {"/bin/sh", "-c", "stty raw  

Por exemplo, se você quiser levar em conta o tempo entre as teclas digitadas, veja o exemplo de código para chegar lá.

Não há maneira portátil de ler caracteres brutos em um console Java.

Algumas soluções alternativas dependentes da plataforma foram apresentadas acima. Mas para ser realmente portátil, você teria que abandonar o modo de console e usar um modo de janelas, por exemplo, AWT ou Swing.

Eu escrevi uma class Java RawConsoleInput que usa o JNA para chamar funções do sistema operacional do Windows e Unix / Linux.

  • No Windows, ele usa _kbhit() e _getwch() de msvcrt.dll.
  • No Unix, ele usa tcsetattr() para alternar o console para o modo não canônico, System.in.available() para verificar se os dados estão disponíveis e System.in.read() para ler os bytes do console. Um CharsetDecoder é usado para converter bytes em caracteres.

Suporta input sem bloqueio e mistura de modo bruto e input de modo de linha normal.

Use jline3 :

Exemplo:

 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();