Running python with command line in java - java

The program is stuck at p2.waitFor() (I tested with printing strings before and after)
public void score() {
this.toXML();
try {
Process p = Runtime
.getRuntime()
.exec("python sumocfg_maker.py Carrefour.net.xml Detectors.det.xml edgedata.csv -ef");
p.waitFor();
Process p2 = Runtime.getRuntime().exec("python simulation.py");
new Thread(new Runnable() {
public void run() {
BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line = null;
try {
while ((line = input.readLine()) != null)
System.out.println(line);
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
p2.waitFor();
} catch (Exception e) {
e.printStackTrace();
}
}
and simulation.py is
import os
os.system('cmd /c "sumo -c Simulation.sumocfg --duration-log.statistics --log duration.txt)
The simulation.py runs fine on its own. When I put the command in simulation.py in java, I get the same problem.
The System.out.println(line); prints out "Success" and then nothing
I left out code from simulation.py that saves a file that the java reads right after the p2.wait(), and without the p2.wait() the file never changes.

You have
BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream()));
But you need
BufferedReader input = new BufferedReader(new InputStreamReader(p2.getInputStream()));
since p is already finished, the bufferedreader will wait but never receive anything.

Related

Running .exe located in specific folder from java program and read its output

Im trying to run Yolo detector from a java GUI i wrote. I can start the detector using windows cmd like so:
cd <pathToYolo> \\ In my case named :C:\\AI\\Yolo_v4\\darknet\\build\\darknet\\x64
darknet.exe detetctor test <pathToAConfigFile> <pathToAnotherConfigFile> <pathToModelDef> -dont_show <pathToImage>
I tried multiple aproaches. I used Runtime.getRuntime().exec() like so.
try {
String command = "darknet.exe detector test data\\obj.data cfg\\yolov4-obj.cfg backup\\rgbmodel\\yolov4-obj_last.weights -dont_show C:\\Users\\felix\\Desktop\\yoloTestSet\\RGBTest\\IMG_2392.jpg";
Process proc = Runtime.getRuntime().exec("cmd /c start /wait " + command, null,
new File("C:\\AI\\Yolo_v4\\darknet\\build\\darknet\\x64"));
BufferedReader br = new BufferedReader(
new InputStreamReader(proc.getInputStream()));
String line;
while ((line = br.readLine()) != null)
System.out.println(line);
proc.waitFor();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
I also tried:
ProcessBuilder pb = new ProcessBuilder(
"cmd",
"/C",
"start",
"darknet.exe",
"detector",
"test",
"data\\obj.data",
"cfg\\yolov4-obj.cfg",
"backup\\rgbmodel\\yolov4-obj_last.weights",
"-dont_show",
"-ext_output",
"C:\\Users\\felix\\Desktop\\yoloTestSet\\RGBTest\\IMG_2392.jpg"
);
pb.directory(new File("C:\\AI\\Yolo_v4\\darknet\\build\\darknet\\x64"));
try {
Process process = pb.start();
InputStreamReader inputStreamReader = new InputStreamReader(process.getInputStream());
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
String output = null;
while ((output = bufferedReader.readLine()) != null) {
System.out.println(output);
}
//wait for the process to complete
//process.waitFor();
//close the resources
//bufferedReader.close();
process.destroy();
} catch (IOException e) {
e.printStackTrace();
}
Both will run the process and print the desired output on cmd and closes the cmd afterwards. So far its just what i want. My problem now is, how can read this output properly.
br.readLine()
seems to be null.
If I leafe out the "start" before the actuall command, I can read the first line of the output, then everything gets stuck, leaving out "cmd" gives me this error:
Cannot run program "darknet.exe" (in directory "C:\AI\Yolo_v4\darknet\build\darknet\x64"): CreateProcess error=2, The system cannot find the file specified
The doku is a bit short on what the "cmd /C start" part actually does.
I would appreciate some advice on what is the issue here and how to do that properly,
regards Felix
Thanks to Daniel Junglas hint, I found this to be a solution.
try {
String command = "C:\\AI\\Yolo_v4\\darknet\\build\\darknet\\x64\\darknet.exe detector test C:\\AI\\Yolo_v4\\darknet\\build\\darknet\\x64\\data\\obj.data C:\\AI\\Yolo_v4\\darknet\\build\\darknet\\x64\\cfg\\yolov4-obj.cfg C:\\AI\\Yolo_v4\\darknet\\build\\darknet\\x64\\backup\\rgbmodel\\yolov4-obj_last.weights -dont_show -ext_output C:\\Users\\felix\\Desktop\\yoloTestSet\\RGBTest\\IMG_2392.jpg";
Process proc = Runtime.getRuntime().exec(command, null,
new File("C:\\AI\\Yolo_v4\\darknet\\build\\darknet\\x64"));
BufferedReader br = new BufferedReader(
new InputStreamReader(proc.getErrorStream()));
BufferedReader stdInput = new BufferedReader(new
InputStreamReader(proc.getInputStream()));
String line;
while ((line = br.readLine()) != null)
System.out.println(line);
while ((line = stdInput.readLine()) != null)
System.out.println(line);
proc.waitFor();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Some of the desired output was inside the ErrorStream. Also you need full paths and do a minor change to YOLO itself, since there is an internal error raised. "cmd /c start" is not necassery.

Run python script from java as subprocess

I'm trying to execute python code (live from the console, not just opening a single file).
ProcessBuilder builder = new ProcessBuilder("python");
Process process = builder.start();
new Thread(() -> {
try {
process.waitFor();
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
new Thread(() -> {
String line;
final BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
// Ignore line, or do something with it
while (true) try {
if ((line = reader.readLine()) == null) break;
else System.out.println(line);
} catch (IOException e) {
e.printStackTrace();
}
}).start();
final PrintWriter writer = new PrintWriter(new OutputStreamWriter(process.getOutputStream()));
writer.println("1");
writer.println("2 * 2");
I tried this code, but after trying to push the following expressions 1 and 2*2, I don't get a response (evaluation of my expressions).
Does anyone know what the issue is?
Your python code doesn't appear to print anything, and handling multiple threads to read and write to another process is a tricky topic; luckily, the functionality is built-in. You could do
ProcessBuilder builder = new ProcessBuilder("/usr/bin/env", "python",
"-c", "print(2*2); exit()");
builder.inheritIO();
try {
Process process = builder.start();
process.waitFor();
} catch (Exception e) {
e.printStackTrace();
}
Which outputs
4
and terminates. For less trivial Python and Java integration, I would strongly suggest you look here. As for your existing code, you never exit() python and you never flush() your PrintWriter. And you write on the main thread. And you need to pass -i to python, or it won't assume stdin is a console. Changing your code to
ProcessBuilder builder = new ProcessBuilder("/usr/bin/env", "python", "-i");
Process process = builder.start();
new Thread(() -> {
String line;
final BufferedReader reader = new BufferedReader(
new InputStreamReader(process.getInputStream()));
// Ignore line, or do something with it
while (true)
try {
if ((line = reader.readLine()) == null)
break;
else
System.out.println(line);
} catch (IOException e) {
e.printStackTrace();
}
}).start();
new Thread(() -> {
final PrintWriter writer = new PrintWriter(
new OutputStreamWriter(process.getOutputStream()));
writer.println("1");
writer.println("2 * 2");
writer.println("exit()");
writer.flush();
}).start();
Seems to work properly.

Trying to run an exe file created from a cpp file in java

I'm trying to run an executable file created from a cpp program in java. If I double-click the exe file, it works just fine, but if I run the file using ProcessBuilder, it gets stuck for some reason, it prints most of the expected output and doesn't continue, also making the entire Java program not responding.
here's my code:
String filePath = FirstScreenController.getFile().getPath();
ProcessBuilder launcher = new ProcessBuilder("ClusteringProgram\\Release\\main.exe",filePath);
launcher.redirectErrorStream(true);
try {
/*File file = FirstScreenController.getFile();
Path newPath = Paths.get(System.getProperty("user.dir")+"\\ClusteringProgram").resolve("K12.fasta");//Moving the file to the
Files.copy(Paths.get(file.getPath()), newPath, StandardCopyOption.REPLACE_EXISTING);*/
System.out.println("Execution started");
p = launcher.start();
InputStream stderr = p.getInputStream();
InputStreamReader isr = new InputStreamReader(stderr);
BufferedReader br = new BufferedReader(isr);
String line = null;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
p.waitFor();//Waiting for the process to finish running
System.out.println("Execution completed");
} catch (IOException | InterruptedException e) {e.printStackTrace();}
Close your stream. That's what's causing you to hang. I write code like this quite a bit.
while ((line = br.readLine()) != null) {
System.out.println(line);
}
br.close(); // You need this or p can hang
p.waitFor();
In addition, you called launcher.redirectStandardError(true); so you actually need all this to gather both stdout and stderr together: The whole rest of this answer is wrong. I don't know what is causing the deadlock. I'm leaving the large code fragment here in case it's some strange library bug and it turns out that the dual-thread reading technique is required to work around it.
final object lock = new object();
InputStream stdout = p.getInputStream();
InputStreamReader isr = new InputStreamReader(stdout);
BufferedReader br = new BufferedReader(isr);
final InputStream stderr = p.getErrorStream();
one = new Thread() {
public void run() {
InputStreamReader isr2 = new InputStreamReader(stderr);
BufferedReader br2 = new BufferedReader(isr2);
while ((line2 = br2.readLine()) != null) {
synchronized(lock) {
System.out.println(line2);
}
}
br2.close(); // you need this or p can hang
}
};
one.start();
while ((line = br.readLine()) != null) {
synchronized(lock) {
System.out.println(line);
}
}
br.close(); // You need this or p can hang
for (;;) {
try {
one.join();
break;
} catch (InterruptedException v) {
/* if there's something that might want the main thread's attention handle it here */
}
}
p.waitFor();

Unable to run apktool command on shell from Java

I am trying to use the apktool from a Java program. I'm using this for creating a web service. However this command does not run on the shell from the Java program.
String cmd = "apktool d /home/ridhima/Test.apk" ;
try {
Process p = Runtime.getRuntime().exec(cmd);
BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line = "";
while((line = reader.readLine()) != null)
{
System.out.print(line + "\n");
}
p.waitFor();
}
catch (IOException | InterruptedException e1) {
e1.printStackTrace();
}
The command works perfectly fine directly from the shell.
Thanks but it works fine now. Since apktool is a wrapper script, it is probably not being recognized through the java program. Extracting the apktool.jar directly works.
try {
ProcessBuilder pb = new ProcessBuilder("/home/ridhima/java/jdk1.8.0/bin/java", "-jar", "apktool.jar","d","test.apk");
Process p = pb.start();
BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
while((line = reader.readLine()) != null) {
System.out.print(line + "\n");
}
p.waitFor();
}catch (IOException | InterruptedException e1) {
e1.printStackTrace();
}
You maybe should wait for the process to complete
String cmd = "apktool d /home/ridhima/Test.apk" ;
try {
Process p = Runtime.getRuntime().exec(cmd);
// You maybe should wait for the process to complete
p.waitFor();
BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line = "";
while((line = reader.readLine()) != null)
{
System.out.print(line + "\n");
}
}
catch (IOException | InterruptedException e1) {
e1.printStackTrace();
}
Or you can use ProcessBuilder for the same task
public class Main {
public static void main(String[] args) throws java.io.IOException, java.lang.InterruptedException {
// Create ProcessBuilder instance for UNIX command ls -l
java.lang.ProcessBuilder processBuilder = new java.lang.ProcessBuilder("ls", "-l");
// Create an environment (shell variables)
java.util.Map env = processBuilder.environment();
env.clear();
env.put("COLUMNS", "3");
processBuilder.directory(new java.io.File("/Users"));
java.lang.Process p = processBuilder.start();
}
}

calling a perl script from a java code in a interactive way

Can someone help me in the below scenario,
I need to call a perl script from my java code. The perl script is an interactive code, which gets the input from the user during its execution and continues further to end. So, the example I have used is, the perl script when executed asks for the age by printing in the console "How old are you?", when the user enter some value say '26'. Then it prints "WOW! You are 26 years old!".
When I tried calling this script from my java code, the process waits till I give the value as 26 in the outputstream, while in the inputstream there is no value. Then finally when again I read the inputstream, i get the entire output of the script together. So, here can't I make it interactive?
I have went through many forums and blogs, but couldn't locate any, which exactly target my requirement.
Here is the java code
import java.io.*;
public class InvokePerlScript {
/**
* #param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Process process;
try
{
process = Runtime.getRuntime().exec("cmd /c perl D:\\sudarsan\\eclips~1\\FirstProject\\Command.pl");
try {
BufferedReader in = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line = null;
while ((line = in.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}
try {
BufferedWriter out = new BufferedWriter(new OutputStreamWriter(process.getOutputStream()));
out.write("23");
out.flush();
out.close();
} catch (IOException e) {
e.printStackTrace();
}
process.waitFor();
if(process.exitValue() == 0)
{
System.out.println("Command Successful");
try {
BufferedReader in = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line = null;
while ((line = in.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}
}
else
{
System.out.println("Command Failure");
try {
BufferedReader in = new BufferedReader(new InputStreamReader(process.getErrorStream()));
String line = null;
while ((line = in.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
catch(Exception e)
{
System.out.println("Exception: "+ e.toString());
}
}
}
Perl code is as below
$| = 1;
print "How old are you? \n";
$age = <>;
print "WOW! You are $age years old!";
Thanks in advance,
Sudarsan
Are you calling flush() on the OutputStream in Java after writing the values? If you don't, there's a good chance they'll just be held in the stream's buffer within the Java process, and so never make it to Perl (with the result that both processes end up waiting for the other's IO.)
(Depending on the implementation of the stream this may or may not be necessary, but it certainly wouldn't hurt - and I've been bitten by this in the past. Usually one doesn't need to be as careful, since flushing happens implicitly when close() is called, but here you can't close the stream after you've finished writing.)
It looks like you're trying to read a full line in this code:
BufferedReader in = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line = null;
while ((line = in.readLine()) != null) {
...
However, in your perl code, you are not printing an endline character, so readLine never returns (as per the documentation).

Categories

Resources