Get input from the keyboard without pausing the program - java

I'm writing Java on Windows 7, and I want to be able to work with the input from the keyboard, which I can only presume is the standard input.
I've tried to use BufferedInput, System.in, and Scanner, but all of them require the program to pause and wait for an end of line or return! Is there anyway to just collect and record the data as it is used, and not have to wait for a return?

Here is a quick solution:
public static void main(String[] args) {
Thread inputThread = new Thread(new Runnable() {
#Override
public void run() {
Scanner scan = new Scanner(System.in);
String input = "";
while (true) {
System.out.println("Type something: ");
input = scan.nextLine();
System.out.println("Input: "+input);
}
}
});
inputThread.start();
while (true) {
System.out.println("");
System.out.println("test");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
The main thread prints "test" every second. And the inputThread asks the user to type something then prints what he wrote. It's just a "visual" solution, you certainly don't want to print something while the user is typing.

Related

Java scanner with ANSI Escape sequences and cursor movement displays ^R when moving cursor away and back to scanner

I am working on a CLI Java-based SMS test messaging system and I am using ANSI Escape sequences to move the cursor. Currently, I have a scanner open toward the top of the screen and I am trying to display an incoming message while keeping the scanner open so that if you are typing a message the incoming message will still display and you can resume typing where you left off. The only problem is that after the cursor moves to display the message and come back if I attempt to backspace some of the tests already in the scanner, the text is moved down and "^R" is displayed. Example:
>before cursor movement
>cursormoved^R
cursormove
How can I backspace some of the text without having this occur? Code:
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
Thread t1 = new Thread() {
public void run() {
while (true) {
System.out.print(">");
String message = sc.nextLine();
SendMessages.send(message);
}
}
};
Thread t2 = new Thread() {
public void run() {
while (true) {
String message = RecMessages.recMessage();
if (message != null) {
System.out.print("\0337"); // save cursor position
System.out.print("\n" + message);
System.out.print("\0338"); // restore saved curor position
}
}
}
};
t1.start();
t2.start();
}

How to use nextLine() after sending ControlD EOF

For my team's programming project, we have a board game, where the user has various inputs at different stages.
When the user wants to quit in the middle of the game, we want the user to press Control+D (which throws the NoSuchElementException) which I want to propagate back to the main menu to allow the user to begin a new game without re-running the program.
I run into problems when I try to access any Scanner .next* methods - it throws the same exception with "No line found". As I read somewhere, the EOF makes hasNext* return false.
The EOF completely stops the Scanner, and any new Scanner from working, as I get the same problem. So, the EOF works exactly as I want it to, until we ask for more input from the user.
(I have done this in C successfully)
import java.util.Scanner;
public class Main {
public static void main(String[] args)
{
boolean run = true;
String str;
Scanner scan1 = new Scanner(System.in);
while (run)
{
try
{
System.out.println(scan1.hasNextLine());
str = scan1.nextLine();
System.out.println(str);
}
catch (Exception e)
{
System.out.println("Error");
//scan1.nextLine(); // this throws the "No line found"
run = false;
}
}
Scanner scan2 = new Scanner(System.in);
System.out.println(scan2.next()); // without scan1, this throws the "NoSuchElementException"
}
}
Any ideas on how to continue Scanning after we EOF?

Java - StringBuilder not accessible after while loop in thread

class myThread extends Thread {
myThread(Socket socket) {
Scanner sc = new Scanner(socket);
}
public void run() {
StringBuilder sb = new StringBuilder();
try {
while(sc.hasNext()) {
sb.append(sc.next());
sb.append(" ");
}
System.out.println(sb.toString());
} catch (Exception e) {
System.out.println(e);
}
}
This code doesn't output anything. However, If I move the System.out.println(sb.toString()); into the while loop, it does.
I have no idea why this is, but I need the code to output first AFTER the while loop is complete.
How would one go about to print the StringBuilder.toString() after the while-loop is complete?
The socket is probably never being closed, and the scanner is just blocking on hasNext().
Close the socket and it should finish.

Bug in JLine2? ConsoleReader.clearScreen

EDIT: This feature only occurs when I invoke the clearScreen method of ConsoleReader! Any other changes don't have an effect. Is this then a bug in JLine2?
JLine2:
Why, when I run this, do I get two console prompts directly following each other (----> ---->)?
Is it because two consoles are being created? I do not understand how.
What am I failing to see here?
import java.io.IOException;
import jline.console.ConsoleReader;
class TextUi implements Ui {
private static final String prompt1 = "----> ";
public void homeScreen() {
try {
ConsoleReader con = new ConsoleReader();
con.setPrompt(prompt1);
con.clearScreen();
System.out.println("Press any key to continue...");
con.readCharacter();
con.clearScreen();
System.out.println("Here is a prompt. Do something and press enter to continue...");
String line = con.readLine();
con.clearScreen();
System.out.println("You typed: ");
System.out.println(line);
System.out.println("Press any key to exit. ");
con.readCharacter();
con.clearScreen();
} catch (IOException e) {
e.printStackTrace();
}
}
public void exitSplash() {
System.out.println("Thank You. Goodbye.");
System.out.println("");
}
public void creditsScreen() {
}
public static void main (String argv[]) {
TextUi ui = new TextUi();
ui.homeScreen();
ui.exitSplash();
}
}
This is not a bug, you just need to call con.flush() after each time you call con.clearScreen().
The clearScreen method doesn't calls flush() automatically (it might work in some cases without flushing) but the readLine method does, so the screen is actually clearing only when you call con.readLine(). This is causing to the last System.out.println (before the readLine) to be cleared even it was called after con.clearScreen().
Your code inside the try block should be changed to:
ConsoleReader con = new ConsoleReader();
con.setPrompt(prompt1);
con.clearScreen();
con.flush();
System.out.println("Press any key to continue...");
con.readCharacter();
con.clearScreen();
con.flush();
System.out.println("Here is a prompt. Do something and press enter to continue...");
String line = con.readLine();
con.clearScreen();
con.flush();
System.out.println("You typed: ");
System.out.println(line);
System.out.println("Press any key to exit. ");
con.readCharacter();
con.clearScreen();
con.flush();

Password masking does not terminate the program when needed

I developed the following application in which I needed to masking the PIN and terminate the program after the user has entered the wrong PIN thrice. However, the program terminates only if i close the stopThread at the beginning (I commented it in the code below), however the password masking does not occur for all the three channces when I do so. But, when I close the stopThread just before displaying the login successful screen, the program does not terminate. I need to use ctrl+c to end the program.
Any help is greatly appreciated.
boolean stopThread = false;
boolean hideInput = false;
boolean shortMomentGone = false;
public static double userBal=0.0D;
public void run(){
try{
sleep(500);
} catch(InterruptedException e){
}
shortMomentGone = true;
while(!stopThread){
if(hideInput){
System.out.print("\b*");
}
try{
sleep(1);
} catch(InterruptedException e){
}
}
}
public static final int NB_OF_TRIES = 3;
public void validatePin(){
BankAccount getAll=new BankAccount();
String pin="";
getAll.Login();
Login hideThread =new Login();
hideThread.start();
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
try{
do{
} while(hideThread.shortMomentGone == false );
// Now the hide thread should begin to overwrite any input with "*"
hideThread.hideInput = true; // Read the PIN
System.out.println("\nPIN:");
boolean pinMatch = false;
int i = 0;
while(!pinMatch && i < NB_OF_TRIES) {
hideThread.hideInput = true;
pin = in.readLine();
i++;
//hideThread.stopThread = true; //Program terminates after third attempt
//PIN masking is stopped, if uncommented
System.out.print("\b \b");
if(pin.equals(" ")){
System.out.println("Please do not leave unnecessary spaces!");
getAll.Login();
}else if(pin.equals("")){
System.out.println("Please do not press the enter key without entering the PIN!");
getAll.Login();
}
FileInputStream fileinputstream = new FileInputStream(".\\AccountInfo.txt");
DataInputStream datainputstream = new DataInputStream(fileinputstream);
BufferedReader bufferedreader1 = new BufferedReader(new InputStreamReader(datainputstream));
do
{
String s1;
if((s1 = bufferedreader1.readLine()) == null)
{
break;
}
if(s1.trim().charAt(0) != '#')
{
String as[] = s1.split(" ");
if(pin.equals(as[0]))
{
System.out.println("You have login!");
String s2 = as[2];
userBal = Double.parseDouble(s2);
getAll.balance = userBal;
hideThread.stopThread = true;
getAll.MainMenu();
System.exit(0);
}else if(pin != as[0]){
System.out.println("Invalid PIN!");
getAll.Login();
System.out.println("\n NOTE :- You are only allowed to enter the PIN THREE times. The number of tries remaining before your card is blacklisted are "+i + "\n Please re-enter your PIN");
}
}
} while(true);
datainputstream.close();
}//End of While Loop
}catch(Exception exception)
{
System.err.println((new StringBuilder()).append("Error: ").append(exception.getMessage()).toString());
}//End of try-catch block
}
There's a readPassword() method in java.io.Console, use that. Why do you need a separate thread at all? That makes everything way too complicated.
Regarding your question why this does not close: Java may optimize while(isTrue){} to something like if(isTrue) { while(true) { } } if you don't set isTrue volatile or synchronize the access to isTrue (getter/setter). This optimizations is called hoisting and explained in Effective Java SE, item 66.
Here is an article which explains exactly your problem: echoing * instead of blanks.
http://java.sun.com/developer/technicalArticles/Security/pwordmask/
They are going the complicated way, too but it works. I would prefer blanks over asterisks since that is the easier way to go. Not echoing * is *nix standard afaik.
Actually after I analysed it a but more i realized that the reason the system wont terminate is because it is not kept in the proper place. Therefore, the solution would be to end the program as soon as the while loop is closed and then everything would work fine.
} while(true);
datainputstream.close();
}//End of While Loop
System.exit(0); // After the system is closed the program would terminate after the third attempt
}catch(Exception exception)
{
System.err.println((new StringBuilder()).append("Error: ").append(exception.getMessage()).toString());
}//End of try-catch block

Categories

Resources