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.
Related
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'm trying to make a java program that commands through cmd.exe and prints their output. To do this, I'm using this code:
cmdLine = Runtime.getRuntime().exec("cmd.exe");
cmdLineOut = new BufferedReader(new InputStreamReader(cmdLine.getInputStream()));
cmdLineIn = new PrintWriter(cmdLine.getOutputStream());
// ...
cmdLineIn.println(command);
cmdLineIn.flush();
String s = null;
while ((s = cmdLineOut.readLine()) != null)
System.out.println(s);
Although, when input is given, the output is never printed.
EDIT: Solved
The cmdLineOut.readLine() doesn't return null when the input is empty, it freezes. Since readLine freezes at the end no other code is executed, I just put the printing of the readLine in a seperate thread.
If somebody wants to answer this better, go ahead.
You never actually execute the user's command, at least in the snippet you posted. Also, nearly all command prompt "commands" are actually just programs that are on the default program search path. You should probably just Runtime.getRuntime().exec(user_command) for each command. This means that you will have to set up the input and output streams like you have already done for each command. You are right to get input in a separate thread, since attempting to read input will block the current thread until there is actually input to read.
However, some commands, even under UNIX or Linux systems, are "built-in" (like cd), meaning that the command prompt (aka "shell") handles the commands internally. Your program will have to test the user input to see if they are calling a built-in, and specially handle calls to built-in commands. Your program should actually be portable to non-Windows computers. Of course, the user would use different commands (cp instead ofcopy), but the only part you would have to add would be handling for other OS' shells' lists of built-ins (or simply have your program implement a "cross-platform" set of built-ins - this is your shell program, you get to make the rules).
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)
I am looking to send a character to a Java process running in the background. I found this article https://serverfault.com/questions/178457/can-i-send-some-text-to-the-stdin-of-an-active-process-running-in-a-screen-sessi?answertab=active#comment155464_178470 which I thought would solve the problem, but it actually doesn't.
For testing purposes I added a line
System.out.println("This is what I read "+(int)temp);
where temp is read this way
int temp = inputStreamReader.read();
Something really weird actually happens:
I start the process in a terminal window (not in background this time)
I open another terminal and look up the process' PID
I run the command
echo q > /proc/*pid_of_the_process/fd/0
In the other window this line appears
q
so for some reason I get to see this character in the terminal where the process is running, but it is actually not read by the process, because if that was the case then I would see this line
This is what I read 113
which is what I actually get if I type 'q' from within the terminal window.
Anybody knows why do I get this funny behavior?
I am currently working on a Java project that will allow me to text edit, save, and then execute Python code. I have hit a snag with the execution of this code however.
For executing the code, I have been doing the following:
Process p = Runtime.getRuntime().exec("python someFileName.py",null,new File("someFilePath");
From here, I have a class that takes this process, and tries to take the input and output streams from the process. I have a Timer set with an action listener that will refresh every .01 second.
That is not the problem however. I can receive input just fine if my program consists solely of print statements in python.
If my program contains anything that requires it to block, either raw_input or time.sleep, nothing is displayed.
My actionPerformed method is as follows:
public void actionPerformed(ActionEvent e)
{
try
{
while(inStream.available() > 0)
{
System.out.print((char)inStream.read());
}
while(errStream.available() > 0)
{
System.out.print((char)errStream.read());
}
}
catch(Exception ex)
{
ex.printStackTrace();
}
}
To handle output, I have a KeyListener on a JTextArea that will send the contents of that area to the output stream.
Whenever I have anything in my Python program that requires blocking, no matter what location in the program, the entire thing locks up.
For instance, I have this python program:
import time
print "Welcome to my Program!"
print "Performing calculations"
time.sleep(5)
num = 5
print "Adding 5 to your number"
for x in range(5):
num+=1
print num
print "Finished!"
Nothing will display for the time that it sleeps. I would assume that the things I receive in the Java program would be:
Welcome to my Program!
Performing calculations
...then nothing for five seconds...then
Adding 5 to your number
6
7
8
9
10
Finished!
But nothing is displayed at all until after 5 seconds has elapsed. So I can execute the program, wait 5 seconds, then a flood of text appears.
Or for using raw_input, the same thing happens. So in other words I cannot use this to prompt users for input.
I was hoping I could get some help with this blocking issue so that my text displays gradually as opposed to having to wait for everything to get out of the way with timers or input.
Any help or resources are appreciated. My current OS is a Mac, but I want any solution to be workable on Windows as well (if at all possible).
By default, python scripts run with buffered output. That means you may not see any stdout until the script exits and flushes. All you have to do is launch python with -u to request unbuffered output. Then you will see what you were expecting.
python -u someFileName.py