Can Java Runtime.exec another java program that uses stdin? - java

I have run into an issue where , when using Java Runtime to run another java program, the program freezes because the other program requires stdin . There is a problem with handling the stdin after executing another java program with Runtime exec() .
Here is sample code that I can't get to work. Is this even possible?
import java.util.*;
import java.io.*;
public class ExecNoGobble
{
public static void main(String args[])
{
if (args.length < 1)
{
System.out.println("USAGE: java ExecNoGobble <cmd>");
System.exit(1);
}
try
{
String[] cmd = new String[3];
cmd[0] = "cmd.exe" ;
cmd[1] = "/C" ;
cmd[2] = args[0];
Runtime rt = Runtime.getRuntime();
System.out.println("Execing " + cmd[0] + " " + cmd[1] + " " + cmd[2]);
Process proc = rt.exec(cmd);
int exitVal = proc.waitFor();
System.out.println("ExitValue: " + exitVal);
} catch (Throwable t)
{
t.printStackTrace();
}
}
}
And the ReadInput.java file:
import java.io.*;
public class ReadInput {
public static void main (String[] args) {
// prompt the user to enter their name
System.out.print("Enter your name: ");
// open up standard input
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String userName = null;
// read the username from the command-line; need to use try/catch with the
// readLine() method
try {
userName = br.readLine();
} catch (IOException ioe) {
System.out.println("IO error trying to read your name!");
System.exit(1);
}
System.out.println("Thanks for the name, " + userName);
}
} // end of ReadInput class
And, finally , the batch file that launches it:
#echo off
echo.
echo Try to run a program (click a key to continue)
echo.
pause>nul
java ExecNoGobble "java -cp . ReadInput"
echo.
echo (click a key to end)
pause>nul
I also posted the question here:
http://forums.oracle.com/forums/message.jspa?messageID=9747449

Call the method Process.getOutputStream and feed your input to the returned output stream.
api docs:
public abstract OutputStream getOutputStream()
Gets the output stream of the subprocess. Output to the stream is
piped into the standard input stream of the process represented by
this Process object.
Implementation note: It is a good idea for the output stream to be
buffered.
Returns:
the output stream connected to the normal input of the
subprocess.

Related

Python through java runtime charset problems

I am sending some greek text ("αλεξ") to my python program and I expect to get a popup window showing "αλεξ" but instead I get "αλεξ". Then I print the text parsed in and get it back to my java program, the result is "αλεξ" again! I am assuming the problem is the charset on my python program but I read somewhere that python3 uses by default utf-8.
Here is my Java Program :
public void run() {
try {
Runtime rt = Runtime.getRuntime();
String commands = "python -u C:\\Users\\Alex\\Desktop\\PythonProjects\\inputOutput.py";
Process proc = rt.exec(commands);
// read from terminal of the program
BufferedReader in = new BufferedReader(new InputStreamReader(proc.getInputStream(),Charset.forName("UTF-8")));
// write on the terminal of the program
BufferedWriter out = new BufferedWriter(s=new OutputStreamWriter(proc.getOutputStream(), "UTF-8"));
System.out.println(s.getEncoding());
boolean telegramStarted = false;
String s;
while ((s=in.readLine())!=null) {
System.out.println(s);
if (telegramStarted |s.equals("started")) {
out.write("αλεξ");
out.newLine();
out.flush();
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
Here is the Python Script :
import ctypes
print('started')
while True :
name = input('Enter your name: ')
ctypes.windll.user32.MessageBoxW(0, name, "Greetings", 1)
print('Hello', name, '!')

Sending input to a running JAR via Java process

I want to write a program which executes JARs and gets their output.
When the JAR program has only a print statement it works fine, but when it asks for input during execution, the program freezes.
Code of the JAR file program:
import java.util.*;
public class demo {
public static void main(String r[]) {
Scanner sc = new Scanner(System.in);
System.out.println("Hello ...");
System.out.println("please enter the number :");
int i = sc.nextInt();
System.out.println(" number : " + i);
}
}
Code of the original program which runs the JAR files:
public class jartorun {
public static void main(String arg[]) throws IOException {
String t = "javaw -jar D:\\jarcheck\\temp.jar";
Process p = Runtime.getRuntime().exec(t);
BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line = "";
while ((line = input.readLine()) != null) {
System.out.print(line + "\n");
}
input.close();
}
}
I can give input to the JAR using process.getOutputStream(), but how would I use it so I can create a program which can give input to a JAR and read its output simultaneously?
If you want to run stuff outside the VM use the ProcessBuilder. Works fine for me and you can inherit the IO Stream.
ProcessBuilder builder = new ProcessBuilder("./script.sh",
"parameter1");
builder.directory(new File("/home/user/scripts/"));
builder.inheritIO();
try {
Process p = builder.start();
p.waitFor();
// Wait for to finish
} catch (InterruptedException e) {
e.printStackTrace();
} catch (IOException ioe) {
ioe.printStackTrace();
}
This should also work with Windows batch scripts and paths.
(haven't tried the input though)
You can use p.getOutputStream() to provide input to the launched process.

Multiprocess via processbuilder Communication, freeze at readline() for BufferedReader()

I am trying to allow communication between one program (the program launcher, if you will) and the programs it launches via processbuilder. I have the output working fine, but the input seems to stop when it reaches the readline() method in helloworld (the created process).
Below is helloworld.java:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Scanner;
public class helloworld {
public static void main (String[] args) {
System.out.println ("println(\"Hello World!\")");
System.out.println ("getInput()");
Scanner in = new Scanner(System.in);
BufferedReader br = new BufferedReader(
new InputStreamReader(System.in));
String input = "";
try {
// wait until we have data to complete a readLine()
while (!br.ready()) {
Thread.sleep(200);
}
System.out.println("println(\"Attempting to resolve input\")");
input = br.readLine();
^This is where program hangs^
if(input != null){
System.out.println("println(\"This should appear\")");
}
System.out.println("println(\"input recieved " + input + "\")");
} catch (InterruptedException | IOException e) {
System.out.println("ConsoleInputReadTask() cancelled");
}
System.out.println("println(\"You said: " + input + "\")");
//System.out.println("println(\"You said: " + in. + "!\")");
in.close();
System.exit(0);
}
}
This is where the output (println) from the other process is recieved:
public void run() {
try {
//cfile = files[indexval].getAbsolutePath();
String[] commands =
{
"java", //Calling a java program
"-cp" , //Denoting class path
cfile.substring(0,cfile.lastIndexOf(File.separator) ), //File path
program}; //Class name
ProcessBuilder probuilder = new ProcessBuilder( commands );
//start the process
Process process = probuilder.start();
//Read out dir output
//probuilder.inheritIO(); //Can inherit all IO calls
InputStream is = process.getInputStream();
OutputStream os = process.getOutputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(os));
BufferedReader br = new BufferedReader(isr);
String line;
/*System.out.printf("Output of running %s is:\n",
Arrays.toString(commands));*/
while ((line = br.readLine()) != null) {
myController.runCommand(line, "Please enter something!", bw);
//System.out.println(line);
}
br.close();
os.close();
} catch (IOException e){
e.printStackTrace();
}
System.out.println("programclosed");
}
And here is the function that it calls:
public synchronized void runCommand(String line, Object... arguments) throws IOException {
String[] tokens;
if(line.contains("(")){
tokens = line.split("\\(",2);
switch(tokens[0]){
case "println": //Println - format println(String strng)
tokens[1] = tokens[1].substring(1, tokens[1].length() - 2);
System.out.println(tokens[1]);
break;
case "getInput": //Get input - format getInput(String command, String message, BufferedWriter br)
Scanner reader = new Scanner(System.in);
System.out.println(arguments.length);
System.out.println(((String)arguments[0]));
BufferedWriter in = ((BufferedWriter)arguments[1]);
in.write(reader.nextLine());
System.out.println("sending input");
in.flush();
reader.close();
break;
default:
System.out.println("Invalid command recieved!");
}
} else
System.out.println("Invalid command recieved!");
}
The output I recieve is:
Hello World!
2
Please enter something!
This is a test input
sending input
Attempting to resolve input
As you can see, I successfully exit the while(!br.ready()) loop, and I stop at br.readLine();
I am aware inheritIO() exist, but for this case I am using the BufferedOuput to send commands which are then parsed and sent to the switch statement, which in turn calls the corresponding function. This is because multiple processes could be launched from the process manager, think of the fun when multiple System.in calls arrive, with nothing to determine which process it is for! In addition, this allows for me to call any type of function, even those not related to println or input.
I believe the issue here is a result of the following:
BufferedReader.ready() returns true if there are any characters available to be read. It does not guarantee that there are any carriage returns among them. (docs)
BufferedReader.readLine() looks for a carriage return to complete a line. If one is not found, it blocks.
BufferedWriter.write() does not automatically write a terminating carriage return.
To test whether this is actually the problem, replace this line in runCommand():
in.write(reader.nextLine());
with:
in.write(reader.nextLine() + "\n");

Java program can not find a file that's been just created in a shell script

I am running a shell script from Java program and in that shell script I am echoing its output to a text file, and in the same Java program I am trying to read that newly created text file. However it can not find the file because the file is somehow not being created instantly. How can I make java wait until the file is created?
Here is the part of Java code that reads a file:
public static void main(String[] args)
{
TreeMap <String, Long> myMap = new TreeMap <String, Long>();
Scanner scanner = null;
int runtime = 0;
//populate the map
myMap.put("key", value);
myMap.put("key", value);
List<String> cmdList = new ArrayList<String>();
cmdList.add("/path/to/my/shell/script/shellscript.sh");
for(Map.Entry entry : myMap.entrySet())
{
cmdList.add(entry.getKey().toString());
cmdList.add(entry.getValue().toString());
}
try
{
Process process = Runtime.getRuntime().exec(cmdList.toArray(new String[cmdList.size()]));
File file = new File("/path/to/my/text/file/output.txt");
scanner = new Scanner(file);
while (scanner.hasNextInt())
{
runtime = scanner.nextInt();
}
}
catch (IOException ex){ System.out.println("Could not read the output." + ex.getMessage()); }
System.out.println(runtime);
}
here's the shell script:
i=0
args=("$#")
while [ $i -lt $# ]
do
START = `date +%s`
some operation here
done
echo $END - $START | bc >> output.txt
My simple Java code:
import java.io.File;
import java.io.IOException;
public class WaitForFileSystem {
public static void main(String[] args) throws IOException, InterruptedException {
File file = new File("someFile.txt");
System.out.println("Start:" + file + " " + file.exists());
Process p = Runtime.getRuntime().exec(".../workspace/.../batch.sh");
System.out.println("Processing: " + file + " " + file.exists());
int returnCode = p.waitFor();
System.out.println("End:" + file + " " + file.exists());
}
}
With my simple Shell skript:
echo hello > someFile.txt
Makes this output:
Start:someFile.txt false
Processing: someFile.txt true
End:someFile.txt true
Is this also the way, that you are doing your system call? Did you include a p.waitFor(); in your code?

Capture the output of DOS (command prompt) and display in a JAVA Frame

When I run a python script, the output appears on the DOS ( command prompt in Windows ).
I want the output be displayed on a JAVA Application, i.e. on a window which contians JTextArea. The output should be same as that on the DOS.
So, How do I capture the output from the DOS and insert it into JAVA Application ??
(I tried storing output of the python script in a text file and then reading it using JAVA. But, in that case, the JAVA application waits for the script to finish running first and then displays the output. And, when the output is more than the screen size, a scroll bar appeears, so that I can see the entire output.)
After crowder's comment, I ran this code. but the output is always:
error:
Process said:
import java.io.*;
import java.lang.*;
import java.util.*;
class useGobbler {
public static void main ( String args[] )
{
ProcessBuilder pb;
Process p;
Reader r;
StringBuilder sb;
int ch;
sb = new StringBuilder(2000);
try
{
pb = new ProcessBuilder("python","printHello.py");
p = pb.start();
r = new InputStreamReader(p.getInputStream());
while((ch =r.read() ) != -1)
{
sb.append((char)ch);
}
}
catch(IOException e)
{
System.out.println("error");
}
System.out.println("Process said:" + sb);
}
}
Can anyone tell me what am I doing wrong ??
You can execute the process via a ProcessBuilder, which will give you a Process instance on which you can read the output via the stream returned from getInputStream.
Here's an example that runs the Python script hello.py and builds up its output in a string:
import java.io.Reader;
import java.io.IOException;
import java.io.InputStreamReader;
public class RunPython {
public static final void main(String[] args) {
ProcessBuilder pb;
Process p;
Reader r;
StringBuilder sb;
int ch;
// Start the process, build up its output in a string
sb = new StringBuilder(2000);
try {
// Create the process and start it
pb = new ProcessBuilder("python", "hello.py");
p = pb.start();
// Get access to its output
r = new InputStreamReader(p.getInputStream());
// Read until we run out of output
while ((ch = r.read()) != -1) {
sb.append((char)ch);
}
}
catch (IOException ex) {
// Handle the I/O exception appropriately.
// Here I just dump it out, which is not appropriate
// for real apps.
System.err.println("Exception: " + ex.getMessage());
System.exit(-1);
}
// Do what you want with the string; in this case, I'll output
// it to stdout
System.out.println("Process said: " + sb);
}
}
You can then do whatever you like with the string, including putting it in the JTextArea like any other string. (You could use a BufferedReader around the InputStreamReader if you like, but you get the idea.)
You can connect to the error and inputStream, while Using Runtime.exec() oder ProcessBuilder.
Examples can be found here:
http://www.java-tips.org/java-se-tips/java.util/from-runtime.exec-to-processbuilder.html

Categories

Resources