How to clear the console screen when introducing input in Java? - java

Is there a way to clear the console when the Java program detects the user it's introducing some data?
I'm executing a program that does the following:
User: //enter username
//show data of the username
I want to make it so the user can search for as many users he want until he ends the execution.
To make it clear and nice, after each username search, I want to clear the screen when the program detects the user is typing something (filling the buffer).
Is there any way to do this?
This is the code I'm using to clear the console (this does not detect when the user is typing):
public static void clearScreen() {
System.out.print("\033[H\033[2J");
System.out.flush();
}
Thanks in advance.

You cannot use System.in without pressing the ENTER key at the end. Its the only way. System.in is not aware of the user input until enter is pressed. So if you are using a normal command line to do this, this won't work and you have to stick different raw command lines like jline
For example :
Terminal terminal = TerminalBuilder.builder().system(true).jna(true).build();
terminal.enterRawMode(); //this enters into a raw mode and get's input on reader
reader = terminal.reader();
//finally
reader.close();
You can check it out. Although it highly doesn't make sense to bring in more dependencies unless you really want to and could just stick to a simple while loop
If you are using maven here's the dependency you can use.
<dependency>
<groupId>org.jline</groupId>
<artifactId>jline</artifactId>
</dependency>

By default, a terminal can only output text line by line.
Moving the cursor around, changing colors or clearing the screen requires special escape sequences that are interpreted by the terminal emulator in which you run your application.
C programs in Linux would usually do this via the ncurses library.
Java programs can do something similar with Lanterna (https://github.com/mabe02/lanterna) but within a GUI window. See also this article, which names other alternatives and shows how to use Lanterna: http://rememberjava.com/cli/2017/01/22/ncurses_terminal_libs.html

Related

Typed text displays in console when not asking for input, how can I stop this?

I'm trying to make a simple text-based game using Java in Eclipse, and everything was working just fine until it randomly started to allow you to type at any point in the program instead of just when requesting input with a Scanner. I found this really weird and did what I could to fix it but nothing worked, so now I'm back at square one. When I run my program, I can type anywhere in the console and it actually shows up and I don't want this to happen. This is my first few lines of code and there are obviously no Scanners in here so I don't understand what could be the problem.
This is happening in all of my projects and I really want to get back to coding with it working.
import java.util.Scanner;
public class Game {
public static void main(String[] args) throws InterruptedException {
String com = "Computer: ";
System.out.print(com +"H");
Thread.sleep(75);
System.out.print("i");
Thread.sleep(75);
System.out.println(".");
Thread.sleep(2000);
This is normal behavior for most consoles; it's not coming from Java or your Java code. When you type into the console, it echoes the characters you type back to you.
There do exist ways to turn off echoing. Console.readPassword() will turn it off until you hit Enter. Unfortunately, Console doesn't expose the ability to turn echoing on and off directly, only while asking for a line of input.
The JLine library can turn it on and off with Terminal.echo():
Terminal terminal = TerminalBuilder.terminal();
terminal.echo(false);
Whether this works right might depend on the way in which the program is run; I haven't tried it from Eclipse.
When I tried this, what I typed while echoing was off appeared the next time I turned echo on. Once again, normal console behavior. If you're typing into the console, it's always listening to you. If you don't want that, I found a hack around it, that worked once or twice at least:
// Skip over anything that's been typed in already.
// Re-implementing skip() with read(), because skip() can throw an "Illegal seek"
// error that read() won't.
System.in.read(new byte[System.in.available()]);
terminal.echo(true);

Java concurrent console IO

I wrote multithreaded java server-client sockets app with messaging functionality but I encountered a problem with simultaneous console IO.Main server console is listening for keyboard input and simultaneously printing out messages from the clients. On client side there is a separate thread for printout.
Here is simplified code representation:
public class ServerThread{
....
BufferedReader in = ... (sock.getInputStream);
while(true){
System.out.println(in.readline());
....
public class ServerMain{
.....
BufferedReader keyb = ... (System.in);
while(true){
in = keyb.readLine();
....
The problem occurs while I'm typing something in the main server console and at the same time a message arrives from one of the clients.
That message is then concated to what I was typing on screen and cursor moves to the beginning of the next line waiting for input.
What was typed in previously is stuck in the keyboard buffer, and I cant edit it anymore. Same problem happens on client side.
The question is how can I print messages on screen without disrupting ongoing input?
(inputted text also needs to stay printed on screen as in readLine() default behavior)
I already tried some of the solutions suggested for other similar problems:
In Lanterna and JCurses libraries there's no support for native System.IO streams. I would have to reinvent the wheel and implement it all by myself manually from memory to screen, one char at a time plus build whole console GUI layer.
The other thing was using ANSI codes but I couldn't figure out how to do what I need with them. I could read one input char at a time instead of a whole line, then if message arrives clear the line, move cursor to the beginning and printout, but afterwards in nextline I don't know how to print previously buffered text and still be able to delete chars with backspace.
edit:
GUI is not an option as I want my code to be able to run on a headless server.(also assume that there will be only one terminal, console, shell, and app running per side)
A distinct non-answer, based on: there is only one console.
And that console is an artefact from times when multiple threads weren't a real problem. "Works nicely with multiple threads" was never a requirement for that low level console.
Thus: if you really want a sophisticated solution (that isn't a hack of some sort) simply consider: not using the stdin/stdout console(s).
Instead: write a simple Swing GUI application. Have one text entry field where input is collected, and one or maybe multiple text fields where your output goes. If you want to be fancy, make it a webapp. I am sure that using some framework, you could put together a working thing within a few hours. You will learn more valuable skills by doing that, instead of spending these hours "working around" the fact that you picked the wrong technology for your problem.
Update, given the comment by the OP: then the best I can think of: don't write to the console. Write to different files. Open multiple terminals, and use tools like "tail" to show you what is happening with your output file(s).
Ok, I found the ideal solution myself:
JLine library works in conjunction with default System.IO, also there is no need to create new Terminal objects (you can) or anything else. Simply instead of BufferedReader you use LineReader
String readLine(String prompt, Character mask, String buffer)
prompt (can be null) is the unexpanded prompt pattern that will be displayed to the user on the left of the input line
mask (can also be null) is the character used to hide user input (when reading a password for example)
buffer is the initial content of the input line
Edit: In JLine's docs i found an even better solution:
printAbove
void printAbove(AttributedString str)
Prints a string before the prompt and redraw everything. If the LineReader is not actually reading a line, the string will simply be
printed to the terminal.
Parameters:
str - the string to print*

Is there a way to print text after the line where the user inputs?

I'm looking to print text on a line that is AFTER where the user is inputing their text.
String userInput;
System.out.println("Hello");
userInput = In.getString();
//I want a System.out.print(""); right here, but I want it to appear while
//the user is still typing their input.
Print: "Hello"
User is getting input
Print "I am printing this at the same time that the user is typing"
As mentioned in the comments, keystrokes cannot be captured in raw java console applications.
His could be do e using gui applications like using AWT/Swing GUI.
Since this could be an overkill for your problem, you should know that java suports editing of console outputs in a way.
E.g. if the current output has hello, printing \b character will erase one character from console and it will look like hell.
Perhaps you can think in these lines and build your functionality.
You can put console into raw mode. There is no built-in platform-independent way of getting there. This might be a solution you can implement,
Non blocking console input in Python and Java
got it from here. There are more solutions in there that might be helpful

Filter character of console input in Java

I'm writing a terminal version of my Java application, and this is the first time I do this. I tried Scanner and Console, but as far as I investigated, these classes only allow me to receive user input after he/she finish inputting (no manipulating/filtering).
For example, I want the user inputs his age, but if he inputs a meaningless string, all I can do is validating the string and requesting him to input again. What I really want is only allow him to input integer, i.e when he press any key which is not a number, the character will not be displayed on console. Using Swing and JTextField I can do this easily with DocumentFilter, but with console only, I still haven't found a way.
Any help is appreciated. Thanks all.
Java has something called robot API which u can use to control keyboard mouse etc...
Not the recommended way :)
Since the console is not Java program (its a c program) you have limited way to interface with it, perhaps you can write native API to get more control over it. I have not tried it but if needed use this option.

How to make Java console input dissapear after pressing enter

I'm using the Scanner class to take some input from the user through the console. Whenever the user inputs something in the screen and presses enter the input stays on screen for example:
This is the prompt
// User writes command and presses enter
command
output of command goes here
//Use writes command3
command
output of command goes here
command3
output of command3 goes here
Is there anyway I can make the command entered not stay in the console after pressing enter?
For example:
//User writes command
output of command goes here
Short answer: no, not from directly within Java. Java has very limited control over the console: you can only read and write to it. Whatever is displayed on the console cannot be erased programmatically.
Long answer: in Java, all console operations are handled through input and output streams—System.in is an input stream, and System.out and System.err are output streams. As you can see for yourself, there is no way to modify an output stream in Java—essentially, all an output stream really does is output bytes to some destination (which is one reason why it's called a "stream"—it's one-way).*
The only workaround I can see is to use a Console object (from System.console()) instead. Specifically, the readPassword() method doesn't echo whatever the user types back to the console. However, there are three problems with this approach. First of all, the Console class is only available in Java 1.6. Second, I wouldn't recommend using this for input other than passwords, as it would make entering commands more troublesome than it's supposed to be. And third, it still wouldn't erase the prompt from the screen, which would defeat the purpose of what you're trying to achieve, I'd think.
* - Technically speaking, System.out and System.err are both instances of PrintStream, but PrintStream is pretty much just a flexible version of OutputStream—a PrintStream is still like a normal output stream in that outputting is a one-way operation.
You will struggle to do this with the standard library.
If you don't want to do it yourself, you may be able to do this with a 3rd party library like JLine.
huh - I always assumed that if you sent backspace characters ('\b') to sysout that it would clear - but I never actually tried it (don't do much console programming these days).
Haven't tried that, but the bottom of this thread seems to indicate that it should work.
Note that this might not work in an IDE console, but may work in a regular OS console...
I'll leave actually proving for certain that it works as an exercise to the OP :-)

Categories

Resources