I have a problem. Need to redirect process.getErrorStream(), process.getInputStream() and process.getOutputStream() to JTextPane.
Process is situated in class A, and JTextPane is situated in class B, so there isn't direct connection between them. For this purpose I've create interface. So, I can call method informListener(String message) which appends line to JTextPane. But I can't find any solution which can solve my problem. Are there any nice and easy solutions?
Thanks.
What you need is couple of threads that read the data from the input streams returned by get*Stream methods and append into the text area.
Something like:
final BufferedReader reader = new BufferedReader(new InputStreamReader(process.getErrorStream());
new Thread(new Runnable() {
String line ;
while ((line = reader.readLine()) != null) {
interfaceObject.informListener(line);
}
}).start();
Just ensure that the appending to textPane happens in EDT using SwingUtilities.invokeLater.
The following program works. (I am on OS X):
package snippet;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.logging.Level;
import java.util.logging.Logger;
public class ProcessOutput {
public static void main(String[] args) throws IOException, InterruptedException {
final Process p = Runtime.getRuntime().exec("ls -lR");
final BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
new Thread(new Runnable() {
#Override public void run() {
try {
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
} catch (IOException ex) {
}
}
}).start();
int waitFor = p.waitFor();
System.out.println(waitFor + " is the return");
}
}
Check whether your command is being constructed properly. May be just print it out and see whether you are able to execute it from cmdline.
It doesn't work. InformaListener calls another method. Here is it's code:
HTMLEditorKit kit = new HTMLEditorKit();
HTMLDocument doc = new HTMLDocument();
...
logTextPane.setEditorKit(kit);
logTextPane.setDocument(doc);
public void onLogData(final String message) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
try {
kit.insertHTML(doc, doc.getLength(), message, 0, 0, null);
} catch (BadLocationException ex) {
Logger.getLogger(SummaryPanel.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
Logger.getLogger(SummaryPanel.class.getName()).log(Level.SEVERE, null, ex);
}
}
});
}
And here is code to getErrorStream:
final String exec = "cmd /C start " + batStrPath + "\\upgrade-build.bat";
final Process p = Runtime.getRuntime().exec(exec);
final BufferedReader reader = new BufferedReader(new InputStreamReader(p.getErrorStream()));
new Thread(new Runnable() {
#Override
public void run() {
try {
String line ;
while ((line = reader.readLine()) != null) {
informListener(line);
}
} catch (IOException ex) {
Logger.getLogger(Installer.class.getName()).log(Level.SEVERE, null, ex);
}
}
}).start();
p.waitFor();
Related
Process p = Runtime.getRuntime().exec("myexe.exe");
BufferedReader br = null;
try{
br = new BufferedReader(new InputStreamReader(p.getInputStream(), "GB2312"));
String value = null;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
}finally{
IOUtils.close(br);
}
Then, the output likes below, not the string I want:
Child: Can't read length for data, error code 109
It seems that the problem appears, because of the output of the exe which is too long. Can ProcessBuilder solve it ?
As a general rule of thumb, you should always read the output of Process before you call waitFor (or use a background Thread to read it while you waitFor)
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
public class PBDemo {
public static void main(String[] args) throws Exception {
String s;
ProcessBuilder pb = new ProcessBuilder("myexe.exe");
pb.redirectErrorStream(true);
try {
Process pro = pb.start();
InputConsumer ic = new InputConsumer(pro.getInputStream());
System.out.println("...Waiting");
int exitCode = pro.waitFor();
ic.join();
System.out.println("Process exited with " + exitCode);
} catch (Exception e) {
System.out.println("sorry" + e);
e.printStackTrace();
}
}
public static class InputConsumer extends Thread {
private InputStream is;
public InputConsumer(InputStream is) {
this.is = is;
start();
}
#Override
public void run() {
try {
int in = -1;
while ((in = is.read()) != -1) {
System.out.print((char) in);
}
} catch (IOException exp) {
exp.printStackTrace();
}
}
}
}
In the past, I've either provided an Observer Pattern to the InputConsumer, through which some other party can be notified as new input comes in or otherwised cached the output so I can process it after the process has completed, based on your needs
I am reading a csv file from a location.
Could you please tell me how can I stop the Producer Thread and Consumer Thread incase file is not found in this case ?
Below is my program which creates two threads, Producer and Consumer Threads to read the data from the file
package com.util;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.io.PipedReader;
import java.io.PipedWriter;
import au.com.bytecode.opencsv.CSVReader;
public class TestProgram {
public static void main(String args[]) {
final String startToken = ",Nifty 50 Gainers";
final String endToken = "50 Losers";
final PipedWriter pipedWriter = new PipedWriter();
PipedReader pipedReaderTmp = null;
try {
pipedReaderTmp = new PipedReader(pipedWriter);
} catch (IOException e) {
}
final PipedReader pipedReader = pipedReaderTmp;
// Consumer
new Thread(new Runnable() {
#Override
public void run() {
try {
CSVReader csvReader = new CSVReader(pipedReader);
while (true) {
String[] line = csvReader.readNext(); // blocks until the next line is available
if (line == null)
break; // end of stream has been reached
if (line != null && line.length > 3) {
String indices_name = line[1];
if (indices_name != null) {
System.out.println(indices_name);
}
}
}
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
// Producer
new Thread(new Runnable() {
#Override
public void run() {
try {
BufferedReader br = new BufferedReader(new FileReader(
"C:\\Users\\ravikiranv\\Downloads\\MA050116.csv"));
String line = null;
while ((line = br.readLine()) != null) {
if (startToken.equals(line))
break;
}
while ((line = br.readLine()) != null) {
if (line.contains((endToken))) {
break;
} else {
pipedWriter.write(line + '\n');
}
}
pipedWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
}
}
See the Javadoc for PipedReader.read().
Throws:
IOException - if the pipe is broken, unconnected, closed, or an I/O error occurs.
So just close it and the other end wwil get an IOException.
Note: The PipedReader has some issues - you may find it safer/better to use something like a `BlockingQueue.
You can and should instantiate and start the Threads only if you know the file exists. This keeps you safe from the concerns to stop threads from within.
File file = new File("C:\\Users\\ravikiranv\\Downloads\\MA050116.csv");
if (file.exists()) {
new Thread(new Runnable() { ... }).start();
...
}
If you don't want that for a reason, you could keep a reference to the consumer thread and stop it from within the producer. For an example how to do that, see this answer
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 am trying to call a simple program test.exe which is as simple as-
int main()
{
int a;
cout<<"Welcome\n";
while(cin>>a&&a!=0)
cout<<"you entered "<<a<<endl;
}
I want to run it from a java program as a process, and send+recieve i/o from it. I am using the process with 2 threads as follows-
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class Processproblem {
public static void main(String[] args)throws IOException, InterruptedException {
final Process process;
try {
process = Runtime.getRuntime().exec("test.exe");
} catch (IOException e1) {
e1.printStackTrace();
return;
}
new Thread(new Runnable() {
public void run() {
String line;
BufferedReader br = new BufferedReader(new InputStreamReader(process.getInputStream()));
try {
while ((line = br.readLine()) != null) {
System.out.println("[OUT] " + line);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
new Thread(new Runnable() {
public void run() {
try {
byte[] buffer = new byte[1024];
int reading=0;
System.out.println(reading);
BufferedWriter bw= new BufferedWriter(new OutputStreamWriter(process.getOutputStream()));
while(reading!=-1)
{
reading= System.in.read(buffer);
for(int i = 0; i < buffer.length; i++) {
int intValue = new Byte(buffer[i]).intValue();
if (intValue == 0) {
reading = i;
break;
}
else
{
bw.append((char)intValue);
}
}
bw.newLine();
bw.flush();
}
} catch (Exception e) {
}
}
}
).start();
}
}
But they are not working as expected. When i run the program it just shows the "Welcome\n" message and then stops for input. When i give a integer and press enter in the java console it does nothing.
What am I doing wrong? They are two separate threads so why are they blocking each other? Is there any problem in my concept?
The program waits for your input. Grab the process output stream (using getOutputStream) and write to it.
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.