Unbuffered Standard Input in Java Console Applications

Say you’re writing a Java console application and want to handle user input in an unbuffered mode. That’s said you don’t want the user to press Enter / Return after some typing – you want that every keyboard hit is delivered to your program immediately. Something similar is implemented in metracer for closing the program when user presses ‘q’.  Let’s see how to implement this in Linux.

Bad news: it’s impossible in Java 🙁 The problem is that what we want is to switch a console / terminal into a RAW (or non-canonical) mode. However there is no API in Java to do this because it’s not portable.

Good news: we can workaround this in Linux at least.

Suppose that our program is just a .jar file and we want it to quit when user hits ‘q’ button. Following is the recipe to achieve that:

  1. put a .jar file into a wrapper shell script. In our case this is simply made by concatenation of a test.sh.head and resulting .jar file into a test.sh file;
unbuffered_stdin_in_java_1

Making a maven to embed a .jar file into a wrapper script (test.sh)

  1. in a wrapper shell script save terminal settings ( stty -g);
unbuffered_stdin_in_java_2

Saving terminal state in a wrapper script (test.sh)

  1. in a wrapper shell script issue commands to configure terminal via stty – disable symbols echoing ( stty -echo) and necessity to press Enter / Return ( stty cbreak);
unbuffered_stdin_in_java_3

Put terminal into a raw (non-canonical) mode with disabled symbols echoing and necessity to press enter / return

  1. launch a .jar file by launching a script itself. This trick is that a .jar file is simply a .zip archive with headers in the tail. As such one can put arbitrary code (in our case this is a shell script) before content of .jar file and Java will be able to launch such a shell-jar file;
unbuffered_stdin_in_java_4

Launch .jar file from under a wrapper script (test.sh)

  1. in a program use a Console class to read bytes from a stdin. When program encounters a ‘q’ symbol – make a quit from a program;

  1. in a wrapper shell restore terminal settings to an original state. Not doing so would lead to a broken console (from user point of view, of course 🙂 )
unbuffered_stdin_in_java_5

Restore terminal settings from within a wrapper script (test.sh)

Here is the complete solution: https://github.com/kocherovms/develorium.com/tree/master/unbuffered_stdin_in_java. Result would look like this one:

unbuffered_stdin_in_java_anj

Unbuffered standard input in Java in action

 

 

2 Responses to “Unbuffered Standard Input in Java Console Applications”

  1. Mike says:

    What about not worked “Enter” in this implementation ?

Leave a Reply

Your email address will not be published.