Here is the situation:
I have a java application which executes another java application example.exe (example.exe has some System.out.println("...");)
I want to get the output Stream from example.exe so i tried with something like that:
(looks pretty standard)
final Process process = Runtime.getRuntime().exec("example.exe");
new Thread() {
public void run() {
try {
BufferedReader inputReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line = "";
try {
while((line = inputReader.readLine()) != null) {
inputText = inputText + line;
}
System.out.println(inputText);
} finally {
inputReader.close();
}
} catch(IOException ioe) {
ioe.printStackTrace();
}
}
}.start();
I would like to get the output messages of example.exe but it doesn't work and i don"t understand why, i get one message but not the one from example.exe, probably from java or something else.
Related
I am working on a Server launcher. This launcher runs Minecraft servers.
I want to get colors from the server's process's input like windows command prompt. How can I do that?
My server thread:
serverThread = new RunnableThread("ServerThread-" + serverName) {
#Override
public void onRun() {
if (!getProcess().isAlive()) {
ServerStatusChangeEvent.change(LocalServer.this, StatusType.STOPPED);
closePort();
if(queryTimerTask != null) queryTimerTask.cancel(false);
cancel();
}
try {
final BufferedReader reader = new BufferedReader(
new InputStreamReader(getProcess().getInputStream(), Charset.forName("UTF-8")));
String line;
while ((line = reader.readLine()) != null) {
String l = line;
Platform.runLater(() -> parseLine(l));
}
reader.close();
} catch (final Exception e) {
//empty catch block
}
}
};
Thanks for the answers and sorry for my bad english!
I was trying to get the logcat content into a JTextPane. I used following code hoping it will return the content as String but it freeze and also, doesn't produce an error.
Process exec = null;
try {
exec = Runtime.getRuntime().exec("adb logcat -d");
InputStream errorStream = exec.getErrorStream();
BufferedReader ebr = new BufferedReader(new InputStreamReader(errorStream));
String errorLine;
while ((errorLine = ebr.readLine()) != null) {
System.out.println("[ERROR] :- " + errorLine);
}
if (exec.waitFor() == 0) {
InputStream infoStream = exec.getInputStream();
InputStreamReader isr = new InputStreamReader(infoStream);
BufferedReader ibr = new BufferedReader(isr);
String infoLine;
while ((infoLine = ibr.readLine()) != null) {
System.out.println("[INFO] :- " + infoLine);
}
}
} catch (IOException | InterruptedException ex) {
ex.printStackTrace();
} finally {
if (exec != null) {
exec.destroy();
}
}
I referred to some tutorials but, they were not filling my problem. Is this wrong? Are there any other methods to get the logcat content as a String programmatically? Sorry if this is a dumb question.
The issue you're seeing is that you're trying to process command streams and wait for the executing process, all in the same thread. It's blocking because the process reading the streams is waiting on the process and you're losing the stream input.
What you'll want to do is implement the function that reads/processes the command output (input stream) in another thread and kick off that thread when you start the process.
Second, you'll probably want to use ProcessBuilder rather than Runtime.exec.
Something like this can be adapted to do what you want:
public class Test {
public static void main(String[] args) throws Exception {
String startDir = System.getProperty("user.dir"); // start in current dir (change if needed)
ProcessBuilder pb = new ProcessBuilder("adb","logcat","-d");
pb.directory(new File(startDir)); // start directory
pb.redirectErrorStream(true); // redirect the error stream to stdout
Process p = pb.start(); // start the process
// start a new thread to handle the stream input
new Thread(new ProcessTestRunnable(p)).start();
p.waitFor(); // wait if needed
}
// mimics stream gobbler, but allows user to process the result
static class ProcessTestRunnable implements Runnable {
Process p;
BufferedReader br;
ProcessTestRunnable(Process p) {
this.p = p;
}
public void run() {
try {
InputStreamReader isr = new InputStreamReader(p.getInputStream());
br = new BufferedReader(isr);
String line = null;
while ((line = br.readLine()) != null)
{
// do something with the output here...
}
}
catch (IOException ex) {
ex.printStackTrace();
}
}
}
}
It seems that using BufferedReader to read a process's InputStream
will somehow result in a block I/O behavior.
And the effect is like the program doesn't get the instant input from the process.
I know there are more lines that could be read at that time, but the BufferedReader
just keep waiting for sometime then I can finally get the lines updated.
Here is the code:
While((str=bufferedReader.readLine()!=null) {
System.out.println(str);
}
Is there some kinds of method that can keep reading from the process without blocking
in the while() condition? cause the process won't return null or anything....
You can read the child process output in a separate thread. Something like this
static BlockingQueue<String> queue = new LinkedBlockingDeque<>();
public static void main(String[] args) throws Exception {
Process p = Runtime.getRuntime().exec("cmd /c dir");
final BufferedReader rdr = new BufferedReader(new InputStreamReader(p.getInputStream()));
Thread t = new Thread() {
public void run() {
try {
for (String line; (line = rdr.readLine()) != null;) {
queue.put(line);
}
} catch (Exception e) {
e.printStackTrace();
}
}
};
t.start();
for (;;) {
String line = queue.poll();
if (line != null) {
System.out.println(line);
} else if (!t.isAlive()) {
break;
}
}
}
You can use the NuProcess library for non-blocking I/O to external processes. Consider it a replacement for ProcessBuilder and Process in Java.
I have an IRC bot which hosts game servers given a few arguments. The problem is, once it hosts a server, it stops listening to IRC (meaning realistically, only one server can be hosted at a time). This is not what I want.
I assumed threading would be the answer to my problem, but I can't seem to get it to work. It appears that it doesn't actually start in another thread?
Here is my main class which starts and runs the method via threading:
// Everything is okay, run the server.
Runnable r = new Server(this, channel);
Thread thread = new Thread(r);
thread.start();
And here is the Server class which (presumably) controls the threading:
public class Server extends PircBot implements Runnable {
public void run() {
}
public Server (bot BotRun, String channel) {
String names[] = org.bestever.bebot.bot.hostbuilder.split(" ");
ProcessBuilder pb = new ProcessBuilder(names);
pb.redirectErrorStream(true);
try {
Process proc = pb.start();
BufferedReader br = new BufferedReader(new InputStreamReader(proc.getInputStream()));
String strLine = null;
while((strLine = br.readLine()) != null) {
// Returns UDP Initialized if the server was successfully started
if (strLine.equalsIgnoreCase("UDP Initialized.")) {
BotRun.sendMessage(channel, "Server started successfully.");
}
// Returns Bad Hex Number if there is a problem with the WAD file
else if (strLine.startsWith("Bad hex number")) {
BotRun.sendMessage(channel, "Error starting server: "+strLine);
}
System.out.println(strLine);
}
Thread.currentThread().interrupt();
} catch (IOException e) {
e.printStackTrace();
}
}
Have I not actually started it in a thread? Thanks for any help!
I am afraid, not.
Server class should be more like:
public class Server extends PircBot implements Runnable {
private bot BotRun;
private String channel;
public void run() {
String names[] = org.bestever.bebot.bot.hostbuilder.split(" ");
ProcessBuilder pb = new ProcessBuilder(names);
pb.redirectErrorStream(true);
try {
Process proc = pb.start();
Reader reader = new InputStreamReader(proc.getInputStream());
BufferedReader br = new BufferedReader(new InputStreamReader(proc.getInputStream()));
String strLine = null;
while((strLine = br.readLine()) != null) {
// Returns UDP Initialized if the server was successfully started
if (strLine.equalsIgnoreCase("UDP Initialized.")) {
BotRun.sendMessage(channel, "Server started successfully.");
}
// Returns Bad Hex Number if there is a problem with the WAD file
else if (strLine.startsWith("Bad hex number")) {
BotRun.sendMessage(channel, "Error starting server: "+strLine);
}
System.out.println(strLine);
}
reader.close();
Thread.currentThread().interrupt();
} catch (IOException e) {
e.printStackTrace();
}
}
public Server (bot BotRun, String channel) {
this.BotRun = BotRun;
this.channel = channel;
}
}
Your run() method is empty; it starts, does nothing, and ends.
I am trying to interact with another process in Java. It goes like this...
Runtime rt;
Process pr=rt.exec("cmd");
then I send some commands to the process using...
BufferedReader processOutput = new BufferedReader(new InputStreamReader(pr.getInputStream()));
BufferedWriter processInput = new BufferedWriter(new OutputStreamWriter(pr.getOutputStream()));
processInput.write("gdb");
processInput.flush();
I don't care about the output for now.. so I try to ignore it using..
while(processOutput.readLine() != null);
but this loops hangs forever. I know this is because process is still running and doesn't sends a null. I don't want to terminate it now. I have to send commands based on user Input and then get the output..
How to do this? In other words I want to flush the Process output stream or ignore it after executing some commands and read it only when I want to.
Use a separate thread to read the output. This way, as long as there is output it will be read, but will not block you.
For example, create such a class:
public class ReaderThread extends Thread {
private BufferedReader reader = null;
public ReaderThread(BufferedReader reader) {
this.reader = reader;
}
#Override
public void run() {
String line = null;
try {
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
}
catch(IOException exception) {
System.out.println("!!Error: " + exception.getMessage());
}
}
}
And in your main class, instead of while(processOutput.readLine() != null);, call:
ReaderThread reader = new ReaderThread(processOutput);
reader.start();