2009-06-30 33 views
83

¿Hay alguna manera fácil de leer un solo carácter de la consola cuando el usuario lo está escribiendo en Java? ¿Es posible? He intentado con estos métodos, pero todos ellos esperar a que el usuario pulse enter clave:¿Cómo leer un solo carácter de la consola en Java (como lo escribe el usuario)?

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

estoy empezando a pensar que System.in no tiene conocimiento de la entrada del usuario hasta que entran es presionado.

Respuesta

50

Lo que quiere hacer es poner la consola en modo "crudo" (edición de línea anulada y no se requiere tecla enter) en oposición al modo "cocinado" (edición de línea con la tecla Intro). En sistemas UNIX, stty 'command puede cambiar los modos.

Ahora, con respecto a Java ... ver Non blocking console input in Python and Java. Extracto:

Si el programa debe estar basado en la consola, debe de cambiar su terminal a cabo de modo de línea en modo de caracteres, y recordar para restaurarlo antes abandona su programa . No existe una forma portátil de hacer esto en todos los sistemas operativos .

Una de las sugerencias es utilizar JNI. De nuevo, eso no es muy portátil. Otra sugerencia al final del hilo, y en común con la publicación anterior, es mirar usando jCurses.

+4

JCurses no es muy portátil ya sea .... Desde el README JCurses: "JCurses consta de dos partes: la parte independiente plattform, y plattform dependiente parte, que consiste en una biblioteca compartida nativa que hace que las operaciones primitivas de entrada y salida estén disponibles para la primera parte ". –

+2

@RyanFernandes sonidos muy portátil para mí - única herramienta que puede ejecutarse en varios sistemas (usando diferentes dependencias) – Antoniossss

20

Tienes que golpear la consola en modo raw. No hay una forma incorporada de plataforma independiente para llegar allí. jCurses might be interesting, though.

en un sistema UNIX, esto podría funcionar:

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

For example, if you want to take into account the time between keystrokes, here's sample code to get there.

+0

funcionó bien para mí en Linux – MrSmith42

+0

Trabajado en Mac también. Probablemente desee mencionar que 'stty cooked Kelvin

+0

El enlace "Por ejemplo ..." ahora está muerto. –

13

No hay manera portátil para leer caracteres primas desde una consola de Java.

Algunas soluciones temporales dependientes de la plataforma se han presentado arriba. Pero para ser realmente portátil, debe abandonar el modo de consola y usar un modo de ventana, p. AWT o Swing.

+11

No entiendo por qué, por ejemplo, Mono (o CLR) tiene el 'System.Console.ReadKey' que funciona en todas las plataformas. Java también distribuye JVM y JRE para cada plataforma con bibliotecas e implementaciones dependientes de la plataforma, por lo que no es excusa. –

6

He escrito una clase de Java RawConsoleInput que usa JNA para llamar a las funciones del sistema operativo de Windows y Unix/Linux.

  • En Windows se utiliza _kbhit() y _getwch() de msvcrt.dll.
  • En Unix utiliza tcsetattr() para cambiar la consola a modo no canónico, System.in.available() para verificar si los datos están disponibles y System.in.read() para leer los bytes de la consola. Un CharsetDecoder se usa para convertir bytes a caracteres.

Admite la entrada sin bloqueo y la mezcla del modo sin procesar y la entrada de modo de línea normal.

+0

¿Cuán fuertemente ha sido probado/probado el estrés? –

+1

@QPaysTaxes La prueba de estrés es difícil para la entrada de la consola. Creo que, en este caso, sería más importante probarlo en varios entornos (diferentes versiones de Windows/Linux, 64/32 bit, Linux vía SSH, Telnet, puerto serie o consola de escritorio, etc.). Hasta ahora solo lo uso en mis herramientas de prueba privadas. Pero el código fuente es relativamente pequeño, en comparación con otras soluciones (como JLine2 que usa Jansi). Entonces no hay mucho que pueda salir mal. Lo escribí porque JLine2 no admite la entrada de un solo carácter sin bloquear. –

+0

Eso es lo que quise decir con stress-tested: probablemente sea la palabra incorrecta; mi error. De todos modos, bien! He robado^H^H^H^H^H^Hused en un proyecto mío para la escuela y ayudó un montón. –

0

Uso jline3:

Ejemplo:

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