Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java Console output overlapping Scanner

Tags:

java

I'm trying to create a console input system which at the same time is able to print output:

new Thread(() ->{ //asynchronous output test every 2 sec
        while(true) {
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            System.out.println("test");
        }
    }).start();

This is how i get the user input:

String line = scanner.nextLine();

However when I'm typing and there's an output at the same time, this is the result:

Test
Test
TestI'm try
Testing to type

Is there a way to display the input line always at the bottom of the console?

like image 968
Kevin Meyer Avatar asked Dec 05 '25 04:12

Kevin Meyer


1 Answers

The solution would be to get the user's input every time he types and store what is actually written in a variable. Then, before writing "Test", clear the amount of characters your user's input is made of by printing \b several times in the console. After that you can print the user's input again to make it feel like "Test" was just printed above.

The tricky part is to get the user's input just as he types. I used the JLine lib in order to achieve that. Also I made sure that the "test" printing thread was getting the inputLine in a synchronized way for thread safety.

private static String inputLine = "";

synchronized static String getInputLine() {
    return inputLine;
}

synchronized static void setInputLine(String line) {
    inputLine = line;
}

public static void main(String[] args) {

    char c;
    char allowed[] = {'a','b','c','d','e','f','g','h','i','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','\n','\r','\b'};

    ConsoleReader reader;
    PrintWriter out = new PrintWriter(System.out);

    new Thread(() ->{ //Asynchronous output test every 2 sec
        while(true) {
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            String erase = ""; //Prepare a string as long as the input made \b characters
            for(int i = 0 ; i < getInputLine().length() ; i++)
                erase += '\b';

            String whitespace = ""; //Prepare a string of whitespaces to override the characters after "test" (thus -4)  
            for(int i = 0 ; i < getInputLine().length() - 4 ; i++)
                whitespace += ' ';

            out.print(erase); //Erase the input line                
            out.println("test" + whitespace);
            out.print(getInputLine());
            out.flush();
        }
    }).start();

    try {
        reader = new ConsoleReader();
        reader.setBellEnabled(false);

        while(true){
            c = (char) reader.readCharacter(allowed);

            if(c == '\r' || c == '\n') {

                //Do something with the input

                setInputLine("");
                out.println();
            } else if(c == '\b') { //Backspace
                String line = getInputLine();
                setInputLine(line.substring(0, line.length()-1));
                out.print(c);
                out.print(" "); //Print whitespace to erase trailing char
                out.print(c); //Backspace again to send the carret back to the last char
            } else {
                setInputLine(getInputLine() + c);
                out.print(c);
            }

            out.flush();
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
}

This program works for me but only outside of my IDE. Note that the program is stuck in an infinite loop so if you want to shut it down, you have to handle it from the code with a "quit" command for example.

Edit: also set the inputLine in a synchronized way.

like image 111
SystemGlitch Avatar answered Dec 07 '25 20:12

SystemGlitch



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!