I have an EXE, written in python and then convert it into an exe, When i run the exe direclty i can see the output in console realtime, but when i run the exe in java i cannot see the output until the exe complete the process.
I have search online but noting is working, Here is sample code.
package com.imviewer.ai;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class FaceAnalysis implements AILibrary {
private static final Logger log = LoggerFactory.getLogger(FaceAnalysis.class);
private static final String KILL = "taskkill /F /IM ";
private static final String EXE_CPU = "FaceAnalysis-CPU.exe";
private static final String EXE_GPU = "FaceAnalysis-GPU.exe";
List<String> paths = new ArrayList<>();
public FaceAnalysis() {
}
#Override
public void setArguments() {
log.info("Setting arguments");
paths.add(new File(AIUtils.FACE, EXE_CPU).getAbsolutePath());
paths.add("--images=yes");
paths.add("--videos=yes");
paths.add("--csv=no");
paths.add("--folderpath=\"Face\"");
paths.add("--algo=cnn");
paths.add("--gpu=no");
paths.add("--cpus=6");
paths.add("--debug=no");
paths.add("--fpstoproces=5");
paths.add("--upsample=0");
paths.add("--onlydetection=yes");
paths.add("--savefullimages=no");
paths.add("--savefaceimage=no");
paths.add("--enablebox=no");
paths.add("--maxarea=640000");
paths.add("--imageextensions=jpg,png,jpeg,tiff,raw,bmp");
paths.add("--videoextensions=mp4,avi,flv,mpeg,mpg,wmv");
paths.add("--age=1");
paths.add("--gender=1");
paths.add("--expression=1");
}
#Override
public void run() {
}
#Override
public void runEXE() {
log.info("Running Face Exe");
ProcessBuilder builder = new ProcessBuilder(paths);
builder.directory(new File(AIUtils.FACE));
builder.redirectOutput(ProcessBuilder.Redirect.INHERIT);
builder.redirectInput(ProcessBuilder.Redirect.INHERIT);
builder.redirectErrorStream(true);
Process proc;
try {
proc = builder.start();
proc.getOutputStream().close();
// Any error message?
Thread errorGobbler
= new Thread(new StreamGobbler(proc.getErrorStream(), System.err));
// Any output?
Thread outputGobbler
= new Thread(new StreamGobbler(proc.getInputStream(), System.out));
errorGobbler.start();
outputGobbler.start();
// Any error?
int exitVal = proc.waitFor();
errorGobbler.join(); // Handle condition where the
outputGobbler.join(); // process ends before the threads finish
log.info("Exit Value: "+ exitVal);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
log.info("End Running Face EXE");
}
#Override
public boolean checkAlreadyRunning() {
// TODO Auto-generated method stub
return false;
}
#Override
public void close() {
// TODO Auto-generated method stub
}
class StreamGobbler implements Runnable {
private final InputStream is;
private final PrintStream os;
StreamGobbler(InputStream is, PrintStream os) {
this.is = is;
this.os = os;
}
public void run() {
try {
int c;
while ((c = is.read()) != -1)
os.print((char) c);
} catch (IOException x) {
// Handle error
}
}
}
public static void main(String[] args) {
FaceAnalysis face = new FaceAnalysis();
face.setArguments();
face.runEXE();
}
}
Try the approach like this:
public static void main(String[] args) throws IOException {
Process p = new ProcessBuilder().command("ping", "webelement.click").start();
InputStream i = p.getInputStream();
Scanner scanner = new Scanner(i);
while (scanner.hasNextLine()){
System.out.println(scanner.nextLine());
}
}
Related
How to make sure process (java.lang.Process) is alive in Java 1.7. In Java 1.8, there is isAlive() method. How can it be done in Java 1.7.
Thank you!
Probably wait too late, but since I faced the same problem, here is my solution:
Just copy the implementation of the Process.isAlive() method from Java 8:
public boolean isAlive() {
try {
exitValue();
return false;
} catch(IllegalThreadStateException e) {
return true;
}
}
with out knowing about the context of need of the Process. But in general, we could use Threads with Executors framework..
Executors.newCachedThreadPool()
Then submit Tasks to it...
I used the following for monitoring multiple processes launched through a Swing application. It follows the same logic mentioned by #mastah. See whether it helps.
package snippet;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
public class ProcessMonitor extends Thread {
private Process process;
private int exitCode;
public ProcessMonitor(Process process) {
this.process = process;
start();
}
#Override public void run() {
try {
exitCode = process.waitFor();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void setOutputStream(final OutputStream s) {
new Thread(new Runnable() {
#Override public void run() {
InputStream is = process.getInputStream();
int c ;
try {
while((c = is.read()) >= 0) {
s.write(c);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
}
public void setErrorStream(final OutputStream s) {
new Thread(new Runnable() {
#Override public void run() {
InputStream is = process.getErrorStream();
int c ;
try {
while((c = is.read()) >= 0) {
s.write(c);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
}
public int getExitCode() {
return exitCode;
}
public static void main(String[] args) throws IOException, InterruptedException {
if(args.length == 1) {
System.err.println("In child process.. going to sleep for 1 second");
Thread.sleep(1000);
System.err.println("In child process.. done sleep exiting...");
System.exit(-1);
}
String[] pbArgs = new String[] {
"java", "-cp", System.getProperty("java.class.path"), ProcessMonitor.class.getName(), "arg"
};
ProcessBuilder pb = new ProcessBuilder(pbArgs);
pb.redirectErrorStream(true);
System.out.println("Starting process: " + pb.command());
final Process process = pb.start();
ProcessMonitor pm = new ProcessMonitor(process);
pm.setOutputStream(System.err);
while (pm.isAlive()) {
System.out.println("Process is still alive");
Thread.sleep(1000);
}
System.out.println("Process exited with: " + pm.getExitCode());
}
}
I am using xjc to generate classes from xsd. The generation has to happen inside the java code. Right now I have done it like this:
Process child = Runtime.getRuntime().exec(command);
try {
System.out.println("waiting...");
child.waitFor();
System.out.println("waiting ended..");
} catch (InterruptedException e) {
e.printStackTrace();
return false;
}
The output for the above program is:
waiting...
I have to use the classes after they are generated. The problem here is that the subprocess never exits and the control is never back to the java program!
Is there a way to do this without getRuntime().exec() ?
You can actually use the driver class (com.sun.tools.xjc.Driver) behind the command line tool. This worked for me:
import com.sun.tools.xjc.BadCommandLineException;
import com.sun.tools.xjc.Driver;
import com.sun.tools.xjc.XJCListener;
import org.xml.sax.SAXParseException;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
public class Generator {
public static void main(String[] args) throws BadCommandLineException, IOException {
final String targetDir = "jaxb-files";
Path path = Paths.get(targetDir);
if(!Files.exists(path)) {
Files.createDirectories(path);
}
Driver.run(new String[]{"-d", targetDir,
"D:\\dev\\onepoint\\tui\\java\\xsdjsonschema\\src\\main\\xsd\\test.xsd"}, new XJCListener() {
#Override
public void error(SAXParseException e) {
printError(e, "ERROR");
}
#Override
public void fatalError(SAXParseException e) {
printError(e, "FATAL");
}
#Override
public void warning(SAXParseException e) {
printError(e, "WARN");
}
#Override
public void info(SAXParseException e) {
printError(e, "INFO");
}
private void printError(SAXParseException e, String level) {
System.err.printf("%s: SAX Parse exception", level);
e.printStackTrace();
}
});
}
}
try this
Process child = Runtime.getRuntime().exec(command);
BufferedReader in = new BufferedReader(
new InputStreamReader(child.getInputStream()));
String line = null;
while ((line = in.readLine()) != null) {
System.out.println(line);
}
A very good article (When Runtime.exec() won't) says: The only possible time you would use exitValue() instead of waitFor() would be when you don't want your program to block waiting on an external process that may never complete. Instead of using the waitFor() method, I would prefer passing a boolean parameter called waitFor into the exitValue() method to determine whether or not the current thread should wait. A boolean would be more beneficial because exitValue() is a more appropriate name for this method, and it isn't necessary for two methods to perform the same function under different conditions. Such simple condition discrimination is the domain of an input parameter.
I have exactly same situation where my system call would start a process which will keep running until user decides to kill it. If I use '(process.waitFor() == 0)' it will block program there because process will not be completed. Author in article above suggest that exitValue() can be used with 'waitFor' parameter. Did anybody try it out ? Any example would be helpful.
Code:
// Start ProcessBuilder, 'str' contains a command
ProcessBuilder pbuilder = new ProcessBuilder(str);
pbuilder.directory(new File("/root/workspace/Project1"));
pbuilder.redirectErrorStream(true);
Process prcs = pbuilder.start();
AForm.execStatustext.append("\n=> Process is:" + prcs);
// Read output
StringBuilder out = new StringBuilder();
BufferedReader bfrd = new BufferedReader(new InputStreamReader(process.getInputStream()));
String current_line = null, previous_line = null;
while ((current_line = bfrd.readLine()) != null) {
if (!line.equals(previous_line)) {
previous_line = current_line;
out.append(current_line).append('\n');
//System.out.println(line);
}
}
//process.getInputStream().close();
// Send 'Enter' keystroke through BufferedWriter to get control back
BufferedWriter bfrout = new BufferedWriter(new OutputStreamWriter(prcs.getOutputStream()));
bfrout.write("\\r");
bfrout.newLine();
bfrout.flush();
bfrout.write("\\r");
bfrout.newLine();
bfrout.flush();
//process.getOutputStream().close();*/
if (prcs.waitFor() == 0)
System.out.println("Commands executed successfully");
System.exit(0);
This is a "rough" example of some library code I use to launch external processes.
Basically, this uses three threads. The first is used to execute the actually command and then wait till it exists.
The other two deal with the processes output and input streams. This makes these independent of each other prevents the ability for one to block the other.
The whole thing is then tied together with a listener that is notified when something happens.
The error handling could be better (as the fail condition is a little unclear as to what/who actually failed), but the basic concept is there...
This means you can launch the process and not care...(until you want to)
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
public class TestBackgroundProcess {
public static void main(String[] args) {
new TestBackgroundProcess();
}
public TestBackgroundProcess() {
BackgroundProcess bp = new BackgroundProcess("java", "-jar", "dist/BackgroundProcess.jar");
bp.setListener(new ProcessListener() {
#Override
public void charRead(BackgroundProcess process, char value) {
}
#Override
public void lineRead(BackgroundProcess process, String text) {
System.out.println(text);
}
#Override
public void processFailed(BackgroundProcess process, Exception exp) {
System.out.println("Failed...");
exp.printStackTrace();
}
#Override
public void processCompleted(BackgroundProcess process) {
System.out.println("Completed - " + process.getExitValue());
}
});
System.out.println("Execute command...");
bp.start();
bp.send("dir");
bp.send("exit");
System.out.println("I'm not waiting here...");
}
public interface ProcessListener {
public void charRead(BackgroundProcess process, char value);
public void lineRead(BackgroundProcess process, String text);
public void processFailed(BackgroundProcess process, Exception exp);
public void processCompleted(BackgroundProcess process);
}
public class BackgroundProcess extends Thread {
private List<String> commands;
private File startIn;
private int exitValue;
private ProcessListener listener;
private OutputQueue outputQueue;
public BackgroundProcess(String... cmds) {
commands = new ArrayList<>(Arrays.asList(cmds));
outputQueue = new OutputQueue(this);
}
public void setStartIn(File startIn) {
this.startIn = startIn;
}
public File getStartIn() {
return startIn;
}
public int getExitValue() {
return exitValue;
}
public void setListener(ProcessListener listener) {
this.listener = listener;
}
public ProcessListener getListener() {
return listener;
}
#Override
public void run() {
ProcessBuilder pb = new ProcessBuilder(commands);
File startIn = getStartIn();
if (startIn != null) {
pb.directory(startIn);
}
pb.redirectError();
Process p;
try {
p = pb.start();
InputStreamConsumer isc = new InputStreamConsumer(p.getInputStream(), this, getListener());
outputQueue.init(p.getOutputStream(), getListener());
outputQueue.start();
p.waitFor();
isc.join();
outputQueue.terminate();
outputQueue.join();
ProcessListener listener = getListener();
if (listener != null) {
listener.processCompleted(this);
}
} catch (InterruptedException ex) {
ProcessListener listener = getListener();
if (listener != null) {
listener.processFailed(this, ex);
}
} catch (IOException ex) {
ProcessListener listener = getListener();
if (listener != null) {
listener.processFailed(this, ex);
}
}
}
public void send(String cmd) {
outputQueue.send(cmd);
}
}
public class OutputQueue extends Thread {
private List<String> cmds;
private OutputStream os;
private ProcessListener listener;
private BackgroundProcess backgroundProcess;
private ReentrantLock waitLock;
private Condition waitCon;
private boolean keepRunning = true;
public OutputQueue(BackgroundProcess bp) {
backgroundProcess = bp;
cmds = new ArrayList<>(25);
waitLock = new ReentrantLock();
waitCon = waitLock.newCondition();
}
public ProcessListener getListener() {
return listener;
}
public OutputStream getOutputStream() {
return os;
}
public BackgroundProcess getBackgroundProcess() {
return backgroundProcess;
}
public void init(OutputStream outputStream, ProcessListener listener) {
os = outputStream;
this.listener = listener;
}
public void send(String cmd) {
waitLock.lock();
try {
cmds.add(cmd);
waitCon.signalAll();
} finally {
waitLock.unlock();
}
}
public void terminate() {
waitLock.lock();
try {
cmds.clear();
keepRunning = false;
waitCon.signalAll();
} finally {
waitLock.unlock();
}
}
#Override
public void run() {
try {
Thread.sleep(500);
} catch (InterruptedException ex) {
}
BackgroundProcess backgroundProcess = getBackgroundProcess();
ProcessListener listener = getListener();
OutputStream outputStream = getOutputStream();
try {
while (keepRunning) {
while (cmds.isEmpty() && keepRunning) {
waitLock.lock();
try {
waitCon.await();
} catch (Exception exp) {
} finally {
waitLock.unlock();
}
}
if (!cmds.isEmpty()) {
waitLock.lock();
try {
while (!cmds.isEmpty()) {
String cmd = cmds.remove(0);
System.out.println("Send " + cmd);
outputStream.write(cmd.getBytes());
outputStream.write('\n');
outputStream.write('\r');
outputStream.flush();
}
} finally {
waitLock.unlock();
}
}
}
} catch (IOException ex) {
if (listener != null) {
listener.processFailed(backgroundProcess, ex);
}
}
}
}
public class InputStreamConsumer extends Thread {
private InputStream is;
private ProcessListener listener;
private BackgroundProcess backgroundProcess;
public InputStreamConsumer(InputStream is, BackgroundProcess backgroundProcess, ProcessListener listener) {
this.is = is;
this.listener = listener;
this.backgroundProcess = backgroundProcess;
start();
}
public ProcessListener getListener() {
return listener;
}
public BackgroundProcess getBackgroundProcess() {
return backgroundProcess;
}
#Override
public void run() {
BackgroundProcess backgroundProcess = getBackgroundProcess();
ProcessListener listener = getListener();
try {
StringBuilder sb = new StringBuilder(64);
int in = -1;
while ((in = is.read()) != -1) {
char value = (char) in;
if (listener != null) {
listener.charRead(backgroundProcess, value);
if (value == '\n' || value == '\r') {
if (sb.length() > 0) {
listener.lineRead(null, sb.toString());
sb.delete(0, sb.length());
}
} else {
sb.append(value);
}
}
}
} catch (IOException ex) {
listener.processFailed(backgroundProcess, ex);
}
}
}
}
Before using waitFor in main thread, create another thread (child) and construct logic for your termination cases in this new thread. For example, wait for 10 secs.
If the condition is fulfilled, then interrupt the main thread from the child thread ant handle the following logic on your main thread.
The following code creates a child thread to invoke the process and the main thread does its work until the child finishes successfully.
import java.io.IOException;
public class TestExecution {
public boolean myProcessState = false;
class MyProcess implements Runnable {
public void run() {
//------
Process process;
try {
process = Runtime.getRuntime().exec("your command");
process.waitFor();
int processExitValue = process.exitValue();
if(processExitValue == 0) {
myProcessState = true;
}
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void doMyWork() {
MyProcess myProcess = new MyProcess();
Thread myProcessExecuter = new Thread(myProcess);
myProcessExecuter.start();
while(!myProcessState) {
// do your job until the process exits with success
}
}
public static void main(String[] args) {
TestExecution testExecution = new TestExecution();
testExecution.doMyWork();
}
}
If I use '(process.waitFor() == 0)' it will block program there because process will not be completed.
No it won't. It will block the thread. That's why you have threads.
Author in article above suggest that exitValue() can be used with 'waitFor' parameter
No he doesn't. He is talking about how he would have designed it, if anybody had asked him. But they didn't, and he didn't.
Did anybody try it out ?
You can't. It doesn't exist.
I've spent the past 3 days without much luck on google on how to run a grep process from within Java.
I have the following code to run a grep process, however, I am only getting the first line of the response.
package com.example.parser;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class Main {
public static void main(String[] args) {
try {
Process process = new ProcessBuilder("grep", "-rni", "\"public static void main(\"", "/home/user/dev/java/").start();
BufferedReader br = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line = "";
while((line = br.readLine()) != null) {
System.out.println(line);
}
System.out.println("Exit Code: " + process.exitValue());
} catch (IOException e) {
e.printStackTrace();
}
}
}
I am only getting the following response:
Binary file /home/user/dev/java/Parser/parser/bin/com/example/parser/Main.class matches
Exit Code: 0
When I should be getting the following response:
Binary file /home/user/dev/java/Parser/parser/com/example/parser/Main.class matches
/home/user/dev/java/Parser/parser/src/com/example/parser/Main.java:10: public static void main(String[] args) {
/home/user/dev/java/Parser/parser/src/com/example/parser/Main.java:12: Process process = new ProcessBuilder("grep", "-rni", "\"public static void main(\"", "/home/user/dev/java/Parser/parser").start();
Exit Code: 0
I am wondering why I only get output for the first finding? Is grep forking several processes to run the search and I'm only getting a handle on the first one?
I have also tried running the process from a Thread:
package com.example.parser;
public class Main {
public static void main(String[] args) {
try {
Analyzer analyzer = new Analyzer();
analyzer.start();
analyzer.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
package com.example.parser;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class Analyzer extends Thread {
public Analyzer() {
}
#Override
public void run() {
try {
Process process = new ProcessBuilder("grep", "-rni", "\"public static void main(\"", "/home/user/dev/java/Parser/parser").start();
process.waitFor();
BufferedReader br = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line = "";
while((line = br.readLine()) != null) {
System.out.println(line);
}
System.out.println("Exit Code: " + process.exitValue());
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
As well as the following:
package com.example.parser;
import java.io.IOException;
public class Main {
public static void main(String[] args) {
try {
Process process = new ProcessBuilder("grep", "-rni", "\"public static void main(\"", "/home/user/dev/java/Parser/parser").start();
process.waitFor();
Analyzer analyzer_is = new Analyzer(process.getInputStream());
Analyzer analyzer_es = new Analyzer(process.getErrorStream());
analyzer_is.start();
analyzer_es.start();
analyzer_is.join();
analyzer_es.join();
System.out.println("Exit Code: " + process.exitValue());
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
package com.example.parser;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
public class Analyzer extends Thread {
InputStream is = null;
public Analyzer(InputStream is) {
this.is = is;
}
#Override
public void run() {
try {
BufferedReader br = new BufferedReader(new InputStreamReader(this.is));
String line = "";
while((line = br.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
As suggested by the following article: http://www.javaworld.com/jw-12-2000/jw-1229-traps.html
I was able to solve the issue by launching a shell with the -c flag. The following code does what I had originally intended:
package com.example.parser;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class Main {
public static void main(String[] args) {
try {
List<String> commands = new ArrayList<String>();
commands.add("/bin/sh");
commands.add("-c");
commands.add("grep -rni --include \"*.java\" \"public static void main(\" /home/user/dev/java/Parser/parser");
Process process = new ProcessBuilder(commands).start();
Analyzer analyzer_is = new Analyzer(process.getInputStream());
Analyzer analyzer_es = new Analyzer(process.getErrorStream());
analyzer_is.start();
analyzer_es.start();
process.waitFor();
analyzer_is.join();
analyzer_es.join();
System.out.println("Exit Code: " + process.exitValue());
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
package com.example.parser;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
public class Analyzer extends Thread {
InputStream is = null;
public Analyzer(InputStream is) {
this.is = is;
}
#Override
public void run() {
try {
BufferedReader br = new BufferedReader(new InputStreamReader(this.is));
String line = "";
while((line = br.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
This is probably because you don't wait for the grep to finish.
Use the waitFor method :
Process process = new ProcessBuilder("grep", "-rni", "\"public static void main(\"", "/home/user/dev/java/").start();
BufferedReader br = new BufferedReader(new InputStreamReader(process.getInputStream()));
process.waitFor();
String line = "";
while((line = br.readLine()) != null) {
System.out.println(line);
}
Note that you may also read the output (mainly to get what happens) while it is being processed using
Process process = new ProcessBuilder("grep", "-rni", "\"public static void main(\"", String line;
while (true) {
line = reader.readLine(); // add IO exception catching
if (line != null) {
System.out.println(line);
} else {
Thread.sleep(DELAY); // DELAY could be 100 (ms) for example
}
}
I suppose you're sure a grep launched by the owner of the java program is more than one line long ?
The other reason could be your process is still running but your Java program just exited.
Use the process.waitFor(); and Read your input stream in a thread.
Start the process.
Lunch a thread with the process input stream as the input.
Now wait for the process to exit by using process.waitFor();
This might help!
Have a look at this project for grep in java https://code.google.com/p/grep4j
I need to launch a binary file using Java and then interact with it using input and output streams. I've written a prototype to figure out how it works, but so far the only output I'm getting has been null. When run on its own however the child program produces output. What am I doing wrong?
import java.io.*;
public class Stream {
public static void main(String args[]) {
Process SaddleSumExec = null;
BufferedReader outStream = null;
BufferedReader inStream = null;
try {
SaddleSumExec = Runtime.getRuntime().exec("/home/alex/vendor/program weights.txt list.txt");
}
catch(IOException e) {
System.err.println("Error on inStream.readLine()");
e.printStackTrace();
}
try {
inStream = new BufferedReader(new InputStreamReader
(SaddleSumExec.getInputStream()));
System.out.println(inStream.readLine());
}
catch(IOException e){
System.out.println("Error.");
}
}
}
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
public class Prompt {
//flag to end readers and writer
boolean processEnd = false;
public static void main(String[] args) {
new Prompt();
}
public Prompt() {
Process SaddleSumExec = null;
Input in = new Input(this);
Output out = new Output(this);
Input err = new Input(this);
//thread to read a write console
Thread t1 = new Thread(in);
Thread t2 = new Thread(out);
Thread t3 = new Thread(err);
try {
SaddleSumExec = Runtime
.getRuntime()
.exec(
"ConsoleApplication1/bin/Debug/ConsoleApplication1");
in.input = SaddleSumExec.getInputStream();
err.input = SaddleSumExec.getErrorStream();
out.out = SaddleSumExec.getOutputStream();
t2.start();
t1.start();
t3.start();
SaddleSumExec.waitFor();
processEnd = true;
} catch (IOException e) {
System.err.println("Error on inStream.readLine()");
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public boolean isProcessEnd() {
return processEnd;
}
public void setProcessEnd(boolean processEnd) {
this.processEnd = processEnd;
}
/*Readers of Inputs*/
class Input implements Runnable {
private BufferedReader inStream;
InputStream input;
Prompt parent;
public Input(Prompt prompt) {
// TODO Auto-generated constructor stub
parent = prompt;
}
public void run() {
inStream = new BufferedReader(new InputStreamReader(input));
while (!parent.isProcessEnd()) {
try {
String userInput;
while ((userInput = inStream.readLine()) != null) {
System.out.println(userInput);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
/*Writers of Output*/
class Output implements Runnable {
OutputStream out;
Prompt parent;
public Output(Prompt prompt) {
parent = prompt;
// TODO Auto-generated constructor stub
}
#Override
public void run() {
while (!parent.isProcessEnd()) {
try {
String CurLine = "";
InputStreamReader converter = new InputStreamReader(
System.in);
BufferedReader in = new BufferedReader(converter);
while (!(CurLine.equals("quit"))) {
CurLine = in.readLine();
if (!(CurLine.equals("quit"))) {
out.write((CurLine + "\n").getBytes());
out.flush();
}
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
You don't seem to be waiting for the child process to end so it is possible that the parent process ends before it gets a chance to read the output stream.
Here is an old but excellent article around Runtime.exec
http://www.javaworld.com/jw-12-2000/jw-1229-traps.html
The correct implementation is on this page
http://www.javaworld.com/jw-12-2000/jw-1229-traps.html?page=4
From what I can tell - there could be two problems here :
Are you trying to obtain the access to the stream BEFORE the child program has started reading ?
Are you running the parent process with insufficient access rights?
If you read a null from readLine() it means the peer has closed the stream. There was no output.