JAVA Concurrent stdInput and stdError with process.exec - java

I am trying to read the stdInput and stdError from a process while the process is running. I created a thread to run the process, and that works. In the constructor for the I pass a reference to a Process that is created so I can watch the output from the process. The problem is it does not seem to be linking the reference process leaving it set to null. The goal of all this is to be able to watch the output of the process while the process is still running, currently I am stuck with looking at the output after it is done. I figure this is due to the tread being run but I hope there is a way to do this.
try {
Process p = null;
Thread mythread = new Thread( new SJ(pathF.getText(), fileF.getText(), p, view) ) ;
mythread.start();
BufferedReader stdInput = null;
BufferedReader stdError = null;
String s = null;
stdInput = new BufferedReader(new InputStreamReader(p.getInputStream()));
stdError = new BufferedReader(new InputStreamReader(p.getErrorStream()));
while (mythread.isAlive()) {
while ((s = stdInput.readLine()) != null) { System.out.println(s); view.write( s + "\r\n" ); }
while ((s = stdError.readLine()) != null) { System.out.println(s); view.write( s + "\r\n" ); }
}
} catch ( IOException e ) {}
class SJ implements Runnable {
String Path = "";
String File = "";
public static viewering view;
Process p = null;
public SJ ( String arg1, String arg2, Process p1, viewering view ) {
Path = arg1;
File = arg2;
p = p1;
}
public void run() {
String[] command = new String[5];
command[0] = "cmd";
command[1] = "/C";
command[2] = "compile";
command[3] = Path;
command[4] = File;
BufferedReader stdInput = null;
BufferedReader stdError = null;
String s = null;
try {
p = Runtime.getRuntime().exec( command, null, new File( "C:/Users/michael.b.goff/Documents/java/" ) );
stdInput = new BufferedReader(new InputStreamReader(p.getInputStream()));
stdError = new BufferedReader(new InputStreamReader(p.getErrorStream()));
while ((s = stdInput.readLine()) != null) { System.out.println(s); view.write( s + "\r\n" ); }
while ((s = stdError.readLine()) != null) { System.out.println(s); view.write( s + "\r\n" ); }
} catch ( IOException e ) {}
}
}
Here is the code for the final working scenario
public void actionPerformed(ActionEvent ae) {
frame.setVisible( false );
final Thread mythread = new Thread( new SJ(pathF.getText(), fileF.getText(), view) ) ;
mythread.start();
final Timer ThreadTimer = new Timer( 1000, null );
ThreadTimer.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if (!mythread.isAlive()) {
frame.setVisible( true );
ThreadTimer.stop();
}
}});
ThreadTimer.start();
}
class SJ implements Runnable {
String Path = "";
String File = "";
public static viewering view;
public SJ ( String arg1, String arg2, viewering view1 ) {
Path = arg1;
File = arg2;
view = view1;
}
public void run() {
String[] command = new String[5];
command[0] = "cmd";
command[1] = "/C";
command[2] = "compile";
command[3] = Path;
command[4] = File;
BufferedReader stdInput = null;
BufferedReader stdError = null;
Process p = null;
String s = null;
try {
p = Runtime.getRuntime().exec( command, null, new File( "C:/Users/michael.b.goff/Documents/java/" ) );
stdInput = new BufferedReader(new InputStreamReader(p.getInputStream()));
stdError = new BufferedReader(new InputStreamReader(p.getErrorStream()));
while ((s = stdInput.readLine()) != null) { System.out.println(s); view.write( s + "\r\n" ); }
while ((s = stdError.readLine()) != null) { System.out.println(s); view.write( s + "\r\n" ); }
} catch ( IOException e ) {}
}
}

Ok, that's a completly different problem. And now I understand your real problem. If you excute the first part of your code in the click listener of a button, Swings event loop which is running in an own thread hangs for a while. Then you have to use a Thread. ;-)
Look at the last answer in this question:
Printing a Java InputStream from a Process

Related

I'm writing a method using spring-boot that calls a.py file, and when I request this method, the code for py doesn't run

I call the.py file in a basic java project and it takes about 30 seconds to run.
import java.io.BufferedReader;
import java.io.InputStreamReader;
public class Main {
public static void main(String[] args) {
Process proc;
String line ="";
BufferedReader in;
try {
proc = Runtime.getRuntime().exec("D:\\anaconda\\python.exe " +
"D:/2017/Python/pythonProject8/main.py " +
"D:\\2017\\Python\\pythonProject8\\flower1.jpg");
proc.waitFor();
in = new BufferedReader(new InputStreamReader(proc.getInputStream()));
while ((line = in.readLine()) != null) {
System.out.println(line);
}
in.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
result:
enter image description here
But this code is skipped when I use spring-boot.
#GetMapping("test")
public String test(){
System.out.println(1);
Process proc;
String line = "";
String result = "";
try {
proc = Runtime.getRuntime().exec("D:\\anaconda\\python.exe " +
"D:/2017/Python/pythonProject8/main.py " +
"D:\\2017\\Python\\pythonProject8\\flower3.jpg");// 执行py文件
proc.waitFor();
BufferedReader in = new BufferedReader(new InputStreamReader(proc.getInputStream()));
while ((line = in.readLine()) != null) {
System.out.println(line);
result += line;
}
in.close();
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(2);
return result;
}
result:
enter image description here
I want to know how to run spring-boot properly.
thanks.
If your.py file takes a long time to run then you shouldn't use Process and use ProcessBuilder instead.
public ArrayList<String> getPasswords(String path) throws IOException {
String result = "";
ProcessBuilder processBuilder = new ProcessBuilder("D:\\anaconda\\python.exe ", "D:\\2017\\Python\\pythonProject8\\main.py",path);
//The path here is me.py needs to be passed in
processBuilder.redirectErrorStream(true);
final Process process = processBuilder.start();
final BufferedReader in = new BufferedReader(new InputStreamReader(process.getInputStream()));
String s = null;
int i = 0;
while ((s = in.readLine()) != null)//This if is I need to ignore some of the output
{
i++;
if (i >6) {
result += s + '\n';
}
}
if (!result.equals("")){
return new ArrayList<String>(Arrays.asList(result.split("\n")));
}
return new ArrayList<String>();
}
You may run an error "DLL load failed while importing XXXX".
Please update the packages required for python.

How to read process builder input and error streams?

I tried to read a process'es std out and error using the solutions in How to redirect Process Builder's output to a string?, but it does not output anything.
Shouldn't there be a way to attach a stream reader to the process builder before starting the process?
/*
private String getInputAsString(InputStream is)
{
try(java.util.Scanner s = new java.util.Scanner(is))
{
return s.useDelimiter("\\A").hasNext() ? s.next() : "";
}
}
*/
private static BufferedReader getOutput(Process p) {
return new BufferedReader(new InputStreamReader(p.getInputStream()));
}
private static BufferedReader getError(Process p) {
return new BufferedReader(new InputStreamReader(p.getErrorStream()));
}
List<String> args = new ArrayList<String>();
args.add ("cmd"); // command name
args.add ("/c");
args.add ("start");
args.add (fileName);
ProcessBuilder pb = new ProcessBuilder (args);
pb.directory(new File(Support.getJustThePathFromFile(file)));
Map<String, String> envs = pb.environment();
String path = envs.get("Path");
envs.put("Path", Paths.get(".").toAbsolutePath().normalize().toString() + ";" +path);
//pb.redirectOutput(new Redirect() {});
Process p = pb.start();
//String stdOut = getInputAsString(p.getInputStream());
//String stdErr = getInputAsString(p.getErrorStream());
//System.err.println("stdOut=" + stdOut);
//System.err.println("stdErr=" + stdErr);
try
{
p.waitFor();
BufferedReader output = getOutput(p);
BufferedReader error = getError(p);
String ligne = "";
while ((ligne = output.readLine()) != null) {
System.out.println(ligne);
}
while ((ligne = error.readLine()) != null) {
System.out.println(ligne);
}
}
catch (InterruptedException e)
{
e.printStackTrace();
}

Retrieve output of ProcessBuilder

Say I have a function like this :
public String runCommand(parameters, boolean interactive)
{
Process p = null;
// some code
try
{
final ProcessBuilder pb = new ProcessBuilder(my_command);
pb.inheritIO(); // So the output is displayed on the console
p = pb.start();
p.waitFor();
}
catch( IOException | InterruptedException e )
{
e.printStackTrace();
}
if (interactive )
{
return p.exitValue() + "";
}
else
{
// return the stdout of the process p
}
}
What I'm trying to do is to return the standard output of the process I'm running through ProcessBuilder, only if the interactive boolean is set to false. However, I cannot figure how to redirect the standard output to a variable with ProcessBuilder. Please not that I used inheritIO() so when I use a function like adb shell, the shell is displayed in my console, which is the behaviour I want. So basically, as for now, I can see the standard output in the console, but I don't know how to return it in the function so I can use this value as a variable for future stuff.
try this
Process p = new ProcessBuilder(cmd).start();
Reader rdr = new InputStreamReader(p.getInputStream());
StringBuilder sb = new StringBuilder();
for(int i; (i = rdr.read()) !=-1;) {
sb.append((char)i);
}
String var = sb.toString();
What you can do is getting the output as and when the execution, like this:
pb.redirectErrorStream(true);
Process p;
try {
p = pb.start();
BufferedReader in = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line;
String output = "";
while((line = in.readLine()) != null) {
log.info(line);
output += line + "\n";
}
return output;
} catch (IOException e) {
// ...
}
return null;

Execute System Commands in Java on Mac

I want to be able to make run a system command on Mac OSX from within Java. My code looks like this:
public void checkDisks() throws IOException, InterruptedException {
Process p = Runtime.getRuntime().exec("df -h");
int exitValue = p.waitFor();
System.out.println("Process exitValue:" + exitValue);
BufferedReader reader = new BufferedReader(new InputStreamReader(
p.getInputStream()));
String line = reader.readLine();
while (line != null) {
line = reader.readLine();
}
System.out.println(line);
}
This always returns null and an exitValue of 0. Never done this before in Java so any thoughts or suggestions greatly appreciated.
Your code is almost OK, you just misplaced the println
public void checkDisks() throws IOException, InterruptedException {
Process p = Runtime.getRuntime().exec("df -h");
int exitValue = p.waitFor();
System.out.println("Process exitValue:" + exitValue);
BufferedReader reader = new BufferedReader(new InputStreamReader(
p.getInputStream()));
String line = reader.readLine();
while (line != null) {
line = reader.readLine();
System.out.println(line);
}
}
I believe it's what you're trying to achieve.
try this
public void checkDisks() throws IOException, InterruptedException {
Process p = Runtime.getRuntime().exec(new String[]{"df","-h"});
int exitValue = p.waitFor();
BufferedReader reader = new BufferedReader(new InputStreamReader(
p.getInputStream()));
String line;
while ((line=reader.readLine()) != null) {
System.out.println(line);
}
System.out.println("Process exitValue:" + exitValue);
}

Stop Bufferedreader Process

my packet capture command in linux terminal..
sudo tcpdump -w kbh-ns.pcap -i lo greater 106 and less 106
Process will stop and save captured packet when i Press
^c
I have a code as below that uses BufferedReader to do it
public void SaveCapture() throws IOException
{
List<String> command1 = new ArrayList<String>();
//perintah untuk mecari koneksi ( SIP DIP SPort DPort )
command1.clear();
command1.add("sudo"); command1.add("tcpdump");
command1.add("-w"); command1.add("kbh-ns.pcap"); //write
command1.add("-i"); command1.add("vmnet1"); //interface
command1.add("greater");command1.add("106"); //packet length
command1.add("and");
command1.add("less"); command1.add("106");//packet length
command1.add("-c"); command1.add("20");
ProcessBuilder pb = new ProcessBuilder(command1);
process = pb.start();
ProcessBuilder PB = new ProcessBuilder(command1);
Process TerminalTask = PB.start();
BufferedReader stdInput = new BufferedReader(new InputStreamReader(process.getInputStream()));
String s;
s = stdInput.readLine();
}
it works if i use
command1.add("-c"); command1.add("5");//number of packets to capture
my quetion :
How to make process stop with ^c command with java?
if i use process.destroy()
private void ButtonStopScanActionPerformed(java.awt.event.ActionEvent evt) {
if (process != null)
{
process.destroy();
TxtAreaKet.setText(TxtAreaKet.getText() + "Complete.. \n");
}
end = System.currentTimeMillis();
try {
ReadPacket();
} catch (IOException ex) {
Logger.getLogger(Receiver1.class.getName()).log(Level.SEVERE, null, ex);
}
TxtAreaKet.setText(TxtAreaKet.getText() + "waktu : "+ ((end - start) / 1000.0) + " ms");
}
private void ReadPacket() throws IOException {
List<String> command1 = new ArrayList<String>();
//perintah untuk mecari koneksi ( SIP DIP SPort DPort )
command1.clear();
command1.add("sudo"); command1.add("tcpdump");
command1.add("-r"); command1.add("kbh-ns.pcap"); //read
command1.add("-n");
ProcessBuilder pb = new ProcessBuilder(command1);
process2 = pb.start();
ProcessBuilder PB = new ProcessBuilder(command1);
Process TerminalTask = PB.start();
BufferedReader stdInput = new BufferedReader(new InputStreamReader(process2.getInputStream()));
BufferedReader stdError = new BufferedReader(new InputStreamReader(process2.getErrorStream()));
String s;
long a = 0;
while ((s = stdInput.readLine()) != null)
{
a++;
}
TxtAreaKet.setText(TxtAreaKet.getText() + "Captured Packet : " + a + "\n");
while ((s = stdError.readLine()) != null)
{
TxtAreaKet.setText(TxtAreaKet.getText() + s + "\n");
}
}
that's not really stop my process because..
when i press Stop Scan again
How to make process stop with ^c command with java?
Just call Process.destroy().

Categories