Upon pressing Control C on the command prompt, is there a possibility of interrupting this signal, and prompting the user for input, to confirm they want to exit the program? I am aware that there are signal interrupts, but not on how to modify the signal to allow input.
String user;
Scanner input = new Scanner(System.in);
try {
[...] // Some code
}
catch(NoSuchElementException e) {
System.out.println("You have chosen to exit the program using Control C.\n");
System.out.print("Are you sure you want to exit? Type Yes or No.");
user = input.nextLine();
if(user.equals("yes")) {
System.exit(0);
}
else {
[...] // Return to the main menu
}
Currently, this code catches the Control C signal, outputs the String: "Are you sure you want to exit? [..]" but then refuses to accept input from the user. It waits a second, then the program would exit instead of getting the input from the user to confirm their decision.
However, I want the code to request input from the user upon Control C activation, and if it is yes, exit the program, else return to the main menu, which it seems to not work as intended.
The short answer is: You should really not do that. There is no portable way to prevent an interrupt signal from exiting a Java application.
The longer answer is that might be possible using internal classes such as sun.misc.Signal and sun.misc.SignalHandler. Since these classes are not portable across JVM implementations and may change in later versions you should avoid using them.
What you should do is to provide another standard way of exiting the application such as typing quit and require confirmation when receiving that input.
If you really want to avoid users exiting with ctrl+c you could try running java with -Xrs which should disable the handling of the console signal (NB: I have not tested this and am not really sure how it works)
Related
I am writing a java program (In Intellij) that accepts a command from the user and reacts to the command. The reaction is asynchronous (using a separate thread).
Scanner in = new Scanner(System.in);
String command = null;
do {
System.out.println("Enter command or q to exit: ");
command = in.nextLine();
System.out.println("Received "+command);
obj.react(command);
}while (!command.equals("q"));
The reacting object may take a while to react and prints a message after it finishes.
The problem is that if I start typing a command, and before I finish, the object prints something, the typed command is lost.
For example Here is a problematic scenario (The text in italics is the user input):
Enter command or q to exit:
go
Received go
goAgainobj finished reacting!
Received
In this case, when I Hit enter after the printed message, the received command is empty.
Is there any way to keep the typed characters even after something was printed?
If you use an actual console, printed output will not affect written input. If you type 'go' and the system prints 'Again', then the in-buffer still knows 'go'. This is unintuitive and bad to read, but it's practical to interrupt running scripts, or other programs.
This may already work on your IDE or your system, depending on OS ans IDE.
If you want something more 'pretty' then you need to fully control input and output, much like the 'top' command in linux (if you happen to know that).
You can handle this way of input better with the Console class. See: https://www.codejava.net/java-se/file-io/3-ways-for-reading-input-from-the-user-in-the-console #3
The most intuitive idea to solve your problem seems to read, and then remove all input at the time you want to print something, and reprint it, so you'd get:
> go
received go
obj finished reacting!
> go
...
You'd basically always print an input line yourself, after first reading and removing the already printed input. This is why you need the Console class, because there, input and output are synchronized, so if you print something, you know that no input will happen in the meantime.
So I'm looking for a similar statement to C++: System("pause");
That runs the code up until a certain point, await's user/keyboard input to continue [Enter], then proceeds.
Everything I can find talks about kill commands, exit systems, threads, etc that basically just close the program down (useful if it's stuck but not for my purposes). The only other references I could find here were to literally pause the program for a set amount of time.
The best way is to use Scanner class. You can do it like this:
System.out.println("Press enter to continue");
new Scanner(System.in).nextLine();
I have a procedural Java Program that has multiple segments that I would like to execute manually (using "Press Enter to Proceed").
Right now I've been trying with System.in.read() or Scanner but if I would make multiple enter presses, it automatically executes the next segment.
how might I regulate this behavior?
I would suggest using BufferedReader instead of System.in.read() . It has a built-in flush mechanism too.
You have to remove everything from the InputStream before you wait for the next enter.
System.in.available() returns the number of bytes currently in the stream.
System.in.read(new byte[System.in.available()]);
This clears the Stream, so now the user has to enter something again.
Note: System.in.skip() doesn't work for some reason.
I want to recognize if a user sent a text, using readline method from BufferedReader. While the user didn't send anything, the Thread keeps sleeping. Is there a way to do this? I'm trying for a long time, but no success yet.. I guess I have to recognize if a ENTER key was pressed.. but I donwt know how to do this.. The interface of my program is the console..
The problem is: I have a client-server program. When a client enters a message, the message prompts on the screen of the another user/client. But, if the user doesn't send a message in 10 seconds, I want a message to appear on the screen.. So I have a Thread.sleep(1000). The problem is I don't know when to wakeuo the Thread.
while((mensagem == null) || (!mensagem.trim().equals(""))) {
Thread.sleep(10000);
sendToAll(output, "[Your turn] ", "");
mensagem = input.readLine();
}
The last line isn't correct also, because I don't want to force the user to type, and this way I'm forcing, 'cause I stop on input.readLine().
SOLUTION:
I resolved the problem using the method setSoTimeout(10000).. This is the code:
public Server(Socket socket) throws SocketException{
this.connection = socket;
this.connection.setSoTimeout(10000);
}
public void run(){
[...]
while((msg != null) && !(msg.trim().equals(""))){
try{
msg = input.readLine();
sendToAll(output, ": ", msg);
} catch (SocketTimeoutException e) {
sendToAll(output, "Time out ", "");
}
}
Thank you all for the ideas!! :)
You read entire lines like this:
String in;
while ((in = br.readLine()) != null) {
// If this is triggered, in contains a whole line and if the input came from console that means enter was pressed
}
Edit: responding to your edit:
input.readLine() is a blocking method. It will continue to attempt read a full line until a line is received, exception thrown, or EOF is reached. Your issue is that you want a 10 seconds timeout. Correct me if I'm wrong.
The way to do this is to create a timer or a thread that isn't blocked by the call to interrupt your .readLine() call. You should have all I/O in its own thread already, so from another thread (main thread, or using a Timer) you need to create a timed event that will interrupt the blocked thread. Example using Timer, add this right before the loop:
java.util.Timer t = new java.util.Timer();
t.schedule(new TimerTask() {
#Override
public void run() {
IOHandlerClass.this.interrupt();
}
}, 10000);
Substitute IOHandlerClass with the name of the class that this code is put inside (you didn't post your code, so I don't know the name).
Now, this will cause an InterruptException to be thrown after 10 seconds unless you stop the timer. So, surround your code with a try-catch to catch that exception and if it's thrown you display the error message. Remember to cancel the timer if you do infact get valid response within the 10 seconds timeout.
You need to understand what is going on here, on both the Java side and the console side.
On the Java side, the readLine() call is simply attempting to read characters until it sees either a valid "end of line" sequence, the end of the input stream. It is a blocking call, and there is no way to specify a timeout in the API that you are using.
On the Console side, console is watching for keyboard events and accumulating them in a line buffer:
When it sees a key event for a data character (a digit, letter, whatever), it adds the character to the buffer.
When it sees a meta character (e.g. a "delete") it performs the appropriate edit on the line buffer. For example, it might delete a character from the line buffer at the 'cursor' position.
When it sees an ENTER key, it adds an end-of-line sequence to the line buffer, and sends the line.
Details will depend on the console program and how the user has configured it. However, the fact remains that until the user types ENTER, nothing will be sent to the "pipe" that connects the console to the Java application. In short, the Java application won't see anything.
What this means is that the Java application can't tell if the user is typing or not.
So what can the Java application do?
You could use a Timer to send an interrupt to the blocked Java thread (the one doing the readLine() call) after a few seconds / minutes. This will cause the readLine() call to unblock and throw an IOException. However, there are problem with this approach:
There is a potential race condition where the timer fires after the readLine() call finishes, and the interrupt goes to application itself. This could cause problems, depending on what the application does with interrupts. You should be able to avoid this using a properly synchronized flag that the primary thread sets when the readLine call returns.
It is not entirely clear, but there are signs that if you get an interrupt on a pipe, the underlying channel is automatically closed. That would mean that you couldn't ask the user for any more input.
The second approach might be to replace your BufferedReader / readLine() code with something that uses NIO channel selectors. Among other things, a Selector allows you to wait with a timeout for a channel to have readable data. You'd then need to implement buffering and readline on top of that.
If you wanted to know if the user had typed at the console, you'd need to put the console into non-line-editing mode. This cannot be done in pure Java, but there are 3rd-party libraries that do this kind of thing.
I have, a game bot which runs through console. I don't think i'm going to code a gui for it but i would like to have the possibility to close the program without CTRL+C cause this just interrupts my program instead of properly cleaning up the code and ensure that theres no leaks.
Should i use som kind of Key Bindings or am i bound to, make a GUI ?
Or how could i go about this ?
I think thats what a shutdown hook is for.
Runtime.getRuntime().addShutdownHook( new Thread() {
#Override
public void run() {
System.out.println("Application shutdown");
}
});
David's answer is good. It may well work for you.
I generally prefer not to deliberately abort a process and then detect that it's coming down to avoid dangling operations. So I'd probably do more like:
Are you processing console inputs as they are entered? IF so, you could just have a console command that tells the app to shut down, and check for this in whatever your process is of handling console inputs. Or if you mean that the app just runs with no user input, you could just periodically check if the console buffer is empty (Console.reader().ready()), and if not, read the console and see if it's the quit command.