Disable user input until Thread.sleep() finishes - java

I'm writing a really basic program, but I've run into a problem. The following is a slice of my code (it is a really silly program, don't try to guess what I'm using it for.)
System.out.println("Please press the Return button a 1000 times.");
for(int i = 1;i < 25;i++) {
input.nextLine();
}
System.out.println("Stop! Stop! Jeez, that was a joke! Do you think I'd make you press that button a 1000 times?");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {}
System.out.println("Let's move on.");
What would happen here is that the program asks the user to press the Return button a 1000 times, which the user would eventually start spamming. The main problem is that after I declare that it was a joke and he only needed to press it 25 times, I'd like to disable the user input, as it's likely that the user will press the button multiple times before realizing that I was just joking. But when the thread.sleep is running, the user input is still active, which leads to multiple problems.
So, is there any way to disable the user input while the program is sleeping?

You can control what to read from the console via application.. But to disable input entirely will be dependent on type of environment application is running on ... For E.g. in cmd line it should not allow you to type in after 25 enters... Whereas in IDE like eclipse, you can type in on console but it will not be read by application after 25 lines.

I believe that it is enough to add 1 line to your code (james large suggestion):
System.out.println("Let's move on.");
System.in.read(new byte[System.in.available()]);//read and ignore

Have a look at this:
public class Main {
private static final String QUIT = "quit";
private static final int COUNT = 1000;
public static void main(String[] args) throws InterruptedException {
new Main(new BufferedReader(new InputStreamReader(System.in))).main();
}
private final BufferedReader in;
private final BlockingQueue<String> lines = new ArrayBlockingQueue<>(1);
private volatile boolean ignore;
public Main(BufferedReader in) {this.in = in;}
private void main() throws InterruptedException {
Thread inputReader = new Thread(this::read, "input-reader");
inputReader.setDaemon(true);
System.out.println("Please press the Return button a "+COUNT+" times.");
inputReader.start();
String line = "";
for(int i = 1;i <= 25;i++) {
line = lines.take();
System.out.println("Good! You entered '"+line+"'. Only "+(COUNT-i)+" left.");
}
System.out.println("Stop! Stop! Jeez, that was a joke! Do you think I'd make you press that button a "+COUNT+" times?");
ignore = true;
Thread.sleep(3000);
ignore = false;
String optionalLine = lines.poll();
if(optionalLine!=null) {
line = optionalLine; System.out.println("Ignored:" + line);
}
System.out.println("Let's move on. Type "+QUIT+" when you're tired.");
while(!QUIT.equalsIgnoreCase(line)){
line = lines.take();
System.out.println(">"+line);
}
System.out.println("Bye.");
}
private void read(){
try {
String line = in.readLine();
while(line!=null){
if (ignore) {
boolean inserted = lines.offer(line);
if (!inserted)
System.out.println("Ignored:" + line);
} else {lines.put(line);}
line = in.readLine();
}
} catch (IOException|InterruptedException e) {e.printStackTrace();}
}
}

Related

`BufferReader` not showing the console input (typed) until ENTER is pressed (only in Windows & Mac, works in Linux)

I wanted to capture user input in two ways, one without timeout (waiting till life) another within some time period (if time exceeds/timeout it should be considered null or no input and move ahead). So I had this code.
public class Main {
public static void main(String[] args) {
System.out.println("Type Something (timeout 5 Sec)");
/* Read input within 5 Sec or done, whichever happens first*/
String inputTimeOut = executeInTime(Main::readInput, 5, TimeUnit.SECONDS);
System.out.println("TimeOut Inupt Given: " + inputTimeOut);
System.out.println("Type Something");
/* Read Input without time restriction */
String input = readInput();
System.out.println("Inupt Given: " + input);
}
public static String executeInTime(Callable<String> call, long wait, TimeUnit unit) {
ExecutorService executorService = Executors.newSingleThreadExecutor();
Future<String> task = executorService.submit(call);
String input = null;
try {
input = task.get(wait, unit);
} catch (InterruptedException | ExecutionException | TimeoutException e) {
task.cancel(true);
} finally {
executorService.shutdown();
}
return input;
}
public static String readInput() {
BufferedReader buffer = new BufferedReader(new InputStreamReader(System.in));
try {
while (!buffer.ready()) {
Thread.sleep(5);
}
String input = buffer.readLine();
return input;
} catch (IOException | InterruptedException e) {
return null;
}
}
}
It worked fine in Linux. Also in Wondows, the end behaviour is same, but there is a small problem.
In windows/Mac, I can't see what I've typed so far until I press enter. In Linux (Ubuntu) it appears as soon as I type.
Any idea why it's behaving differently in windows? And any other solution is also welcomed, as far as it allows the reading operation to be interruptible/killable and common (like my readInput()).
Update:
If I comment this
while (!buffer.ready()) {
Thread.sleep(5);
}
it shows while typing but does not end the execution after timeout.
(I can't use System.exit on timeout, sorry.)

Trying to use Thread.sleep function, catch token has multiple errors

import java.util.Scanner;
public class HelloWorld
{
public static void main(String[] args)
{
Scanner math = new Scanner(System.in);
System.out.println("What is 2 + 2?");
int num = math.nextInt();
System.out.println("Wrong."); // Displays "Wrong." no matter the answer.
{
Thread.sleep(2000); // Adds a timer for 2 seconds.
}
catch(InterruptedException e)
{
System.out.println("Please, try again :-)");
}
int num1 = math.nextInt();
System.out.println(""); //Displays some message.
}
}
The code is supposed to display "What is 2 + 2?", a user inputs an answer, the code returns "Wrong." no matter what the answer. After a 2 second pause, the code displays "Please, try again :-)" and a user inputs an integer and the code returns a message.
The errors occur on the line with the catch token. The errors are:
Syntax error on token "catch", ( expected,
Syntax error, insert "-> LambdaBody" to complete LambdaExpression,
Syntax error, insert "AssignmentOperator Expression" to complete Assignment,
Syntax error, insert ";" to complete Statement
To use a catch in java you need to have a try. It is called a try..catch block. Please read the documentation here
So, adding a try as follows should get rid of the errors you are asking about here :
System.out.println("Wrong."); // Displays "Wrong." no matter the answer.
try // Looks like you missed the try here
{
Thread.sleep(2000); // Adds a timer for 2 seconds.
} catch (InterruptedException e) {
System.out.println("Please, try again :-)");
}
I cant see try block. you can use this way also without try catch. Main method can throw InterruptedException ...
public class HelloWorld {
public static void main(String[] args) throws InterruptedException {
Scanner math = new Scanner(System.in);
System.out.println("What is 2 + 2?");
int num = math.nextInt();
System.out.println("Wrong."); // Displays "Wrong." no matter the answer.
{
Thread.sleep(2000); // Adds a timer for 2 seconds.
}
int num1 = math.nextInt();
System.out.println(""); //Displays some message.
}
}

How would I receive input from console without blocking?

Note: I understand that the console is for debugging and games should use GUI. This is for testing/experience
I'm writing a game that runs at 60fps. Every update, I check to see if the user has entered a String command. If so, it gets passed through, but if not, null is paas through, and the null is ignored.
Scanner is out of the question, since hasNext(), the method used to see if there is data to read, can potentially block and causes problems.
I've tried using BufferedReader.ready(). Not only did I have problems (never returned true), but I've read that it's not recommended for a few reasons.
BufferedReader.available() always returned 0, which in the documentation, it state's that InputStream.available() will always return 0 unless overriden. Here is my attempt:
class Game {
public static void main(String[] args) {
InputReader reader = new InputReader(System.in);
int timePerLoop = 1000/30;
Game game = new Game();
while(true) {
long start = System.nanoTime();
game.update(reader.next());
long end = System.nanoTime();
long sleepTime = timePerLoop + ((start - end) / 10000000);
if(sleepTime > 0)
try {
Thread.sleep(sleepTime);
}catch(InterruptedException e) {
e.printStackTrace();
}
else
Thread.yield();
}
}
public void update(String command) {
if(commands != null) {
//handle command
}
//update game
}
}
InputReader.java
public class InputReader {
private InputStream in;
public InputReader(InputStream stream) {
in = stream;
}
public String next() {
String input = null;
try {
while(in.available > 0) {
if(input == null)
input = "";
input += (char) in.read();
}
}catch(IOException e) {
e.printStackTrace();
}
return input;
}
}
InputStream by itself has the same problem as above. I'm not completely sure what type the object stored in System.in, but using available() yields the same results.
I've tried using the reader() from System.console(), but console() returns null. I've read into the subject, and I am not confused why. This is not the way to do it.
The goal is to check the stream to see if it contains data to read, so I can read the data knowing it won't block.
I do not want to use a separate Thread to handle user input, so please don't recommend or ask why.
The input has to be from the console. No new sockets are to be created in the process. I have read a few topics about it, but none of them clearly states a solution. Is this possible?
As you have said yourself, a custom GUI or an additional thread is the correct way to do this. However in absence of that, have you tried using readLine() for example: String inputR = System.console().readLine();
Some alterations to main():
Replace: InputReader reader = new InputReader(System.in); with:
Console c = System.console();
Replace: game.update(reader.next());
with: game.update(c.readLine());
Edit: This thread could also be helpful: Java: How to get input from System.console()

hasNextInt() From Scanner behaving weirdly

I have a very simple loop that waits for a number (int) and as long as that number is not exitOption it does not leave the loop, however I get an unexpected error, and I don't know what's causing it.
Edit
Adding another snippet so you can compile
public static void main(String[] args) throws FileNotFoundException,
SecurityException,
IOException,
ClassNotFoundException {
while (controller.selectOptionMM());
/Edit
public boolean selectOptionMM() throws SecurityException,
FileNotFoundException,
IOException {
int cmd = ui.getExitOption();
ui.mainMenu();
cmd = utils.readInteger(">>> "); // this is my problem, right here
// code in next snippet
while (cmd <1 || cmd > ui.getExitOption()) {
System.out.println("Invalid command!");
cmd = utils.readInteger(">>> ");
}
switch (cmd) {
case 1:
case 2:
case 3:
case 4: this.repository.close();
return true;
case 5: return false;
}
return false;
}
Here is what fails:
public int readInteger(String cmdPrompt) {
int cmd = 0;
Scanner input = new Scanner(System.in);
System.out.printf(cmdPrompt);
try {
if (input.hasNextInt())
cmd = input.nextInt(); // first time it works
// Second time it does not allow me to input anything
// catches InputMissmatchException, does not print message
// for said catch
// infinitely prints "Invalid command" from previous snippet
} catch (InputMismatchException ime) {
System.out.println("InputMismatchException: " + ime);
} catch (NoSuchElementException nsee) {
System.out.println("NoSuchElementException: " + nsee);
} catch (IllegalStateException ise) {
} finally {
input.close(); // not sure if I should test with if (input != null) THEN close
}
return cmd;
}
First time I pass trough, it reads the number no problem. Now if the number is not 5 (in this case exitOption), it passes again trough readInteger(String cmdPrompt) except this time it jumps to catch (InputMismatchException ime) (debug) except it does not print that message and just jumps to Error, input must be number and Invalid command.
Is something stuck in my input buffer, can I flush it, why is it (input buffer) stuck (with random data)???
I'll try debugging again and see what's stuck in my input buffer, if I can figure out how to see that.
The problem is in the call to input.close() - this causes the underlying input stream to be closed. When the input stream being closed is System.in, bad things happen (namely, you can't read from stdin any more). You should be OK just eliminating this line.
input.hasNextInt()
This line throws the exception if there is no Integer, so instead of it going to else block it forward to catch block. It will never go to else block if exception get caught.

Java: How keep running process in thread and read it's values?

I don't know if this is the best approach so that's why I'm asking your help guys.
This is my problem, I'm developing an app where you have the 'read' button, when the user hit this button then the program start to read some values and save this values in my database, okay ?
So I think when the user hit 'read' I start a thread, that's because the user can do another thing if he wants without the app been freeze.
But I cannot access the values read by this thread.
There's another way to do that ?
EDIT:
private void jtb_readerItemStateChanged(java.awt.event.ItemEvent evt) {
// getting some values provided by the user
if (buttonReaderState()){
if (supervisory == null)
supervisory = new Supervisory(ip, broadcast, deviceID);
supervisory.start();
}
}
// Supervisory class
public void start(){
Scan scan = new Scan();
Thread t = new Thread(scan);
t.start();
threadState = true;
}
class Scan extends Thread{
public void run(){
// inside the tread I have to initiate another 'supervisory' object, is that right ?
Supervisory s = new Supervisory(ip, broadcast, deviceID);
while (threadState){
try {
s.active();
} catch (IOException ioe) {
ioe.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
public void active() throws IOException, Exception {
// getting this values from my hardware like temperature and anothers things.
for (int i = 0; i < ois.size(); i++) {
ObjectIdentifier oi = ois.get(i);
//analog input
if (i == 1)
aI = Float.parseFloat(getPresentValue(localDevice, oi));
//analog output
if (i == 2)
aO = Float.parseFloat(getPresentValue(localDevice, oi));
//binary input
if (i == 3)
bI = getBinaryValue(getPresentValue(localDevice, oi));
//binary output
if (i == 4)
bO = getBinaryValue(getPresentValue(localDevice, oi));
}
}
After reading this values I would like to show this values in the interface that I'm building, but it seems that I cannot have access to these values (aI,aO,bI,bO).
Pass a reference to the interface you have. E.g. you can add a JFrame owner field to Supervisory class and pass your values there.

Categories