Executing a python file from within JAR - java

I am trying to figure out how to reference a python file so that I can execute it within a Java GUI Jar. It needs to be a portable solution, so using absolute paths will not work for me. I have listed my project structure below, and have included the code for how I am trying to execute the python script..I have read things about using resources, but I have been unable to implement this successfully. I appreciate any help you can provide!
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
try {
Runtime rt = Runtime.getRuntime();
Process pr = rt.exec("python /scripts/script.py");
BufferedReader bfr = new BufferedReader(new InputStreamReader(pr.getInputStream()));
String line = "";
while((line = bfr.readLine()) != null)
System.out.println(line);
}
catch(Exception e) {
System.out.println(e.toString());
}
}
--OneStopShop (Project)
--Source Packages
--images
--onestopshop
--Home.java
--scripts
--script.py

Starting a file path with a / means you want to start at the root of your file system.
Your code worked for me by simply removing that leading slash:
public static void main(String[] args) {
try {
File python = new File("scripts/script.py");
System.out.println(python.exists()); // true
Runtime rt = Runtime.getRuntime();
Process pr = rt.exec("python scripts/script.py"); // print('Hello!')
BufferedReader bfr = new BufferedReader(new InputStreamReader(pr.getInputStream()));
String line = "";
while((line = bfr.readLine()) != null)
System.out.println(line);
}
catch(Exception e) {
System.out.println(e.toString());
}
}
// true
// Hello!
// Process finished with exit code 0
The reason why putting a wrong file did not show an error is because this java code only displays the input stream (getInputStream()), not the error stream (getErrorStream()):
public static void main(String[] args) {
try {
Runtime rt = Runtime.getRuntime();
Process pr = rt.exec("python scripts/doesnotexist.py");
BufferedReader bfr = new BufferedReader(new InputStreamReader(pr.getErrorStream()));
String line = "";
while((line = bfr.readLine()) != null)
System.out.println(line);
}
catch(Exception e) {
System.out.println(e.toString());
}
}
// python: can't open file 'scripts/doesnotexist.py': [Errno 2] No such file or directory
// Process finished with exit code 0

Related

Java runtime getInputStream ignores majority of terminal command output

I'm writing a Java program to capture the output of a terminal command. Under "normal" conditions, i.e. where I execute the command directly into the terminal myself, I can see the following result:
However, the output rendered by my Java program only captures a small subset of that, see here:
This is the codebase I'm speaking of:
import java.io.*;
class evmTest {
public static void main(String[] args) {
String evmResult = "";
String evmCommand = "evm --debug --code 7f00000000000000000000000000000000000000000000000000000000000000027f00000000000000000000000000000000000000000000000000000000000000027f00000000000000000000000000000000000000000000000000000000000000020101 run";
try {
Runtime r = Runtime.getRuntime();
Process p = r.exec(evmCommand);
BufferedReader in = new BufferedReader(new
InputStreamReader(p.getInputStream()));
String inputLine;
while ((inputLine = in.readLine()) != null) {
System.out.println(inputLine);
evmResult += inputLine;
}
in.close();
} catch (IOException e) {
System.out.println(e);
}
}
}
Thus far I've not been able to determine why that code is only able to emit the paltry 0x. I've posted this question in the hopes that someone might be able to help me track down the cause of this error.
do it like this:
import java.io.*;
class evmTest {
public static void main(String[] args) {
String evmResult = "";
String evmCommand = "evm --debug --code 7f00000000000000000000000000000000000000000000000000000000000000027f00000000000000000000000000000000000000000000000000000000000000027f00000000000000000000000000000000000000000000000000000000000000020101 run";
try {
Runtime rt = Runtime.getRuntime();
String command = "evm --debug --code 7f00000000000000000000000000000000000000000000000000000000000000027f00000000000000000000000000000000000000000000000000000000000000027f00000000000000000000000000000000000000000000000000000000000000020101 run";
Process proc = rt.exec(command);
BufferedReader stdInput = new BufferedReader(new
InputStreamReader(proc.getInputStream()));
BufferedReader stdError = new BufferedReader(new
InputStreamReader(proc.getErrorStream()));
// read the output from the command
System.out.println("Here is the standard output of the command:\n");
String s = null;
while ((s = stdInput.readLine()) != null) {
System.out.println(s);
}
// read any errors from the attempted command
System.out.println("Here is the standard error of the command (if any):\n");
while ((s = stdError.readLine()) != null) {
System.out.println(s);
}
} catch (IOException e) {
System.out.println(e);
}
}
}

Runtime.getRuntime failed to get output same time but later

I'm currently making firefox addon development GUI tool using Java. However I am stuck when trying to get output of a .bat file.
When I run .bat file using java I can see the output, but there are 3 commands written in the bat file. When first command executes I can get the output simultaneously. But when it execute second command output not coming. And when .bat file exist I get all the output which didn't come simultaneously.
I'm getting output immediately when it execute:
call "C:\mozilla-build\addon-sdk-1.16\bin\activate.bat
But I'm not getting output simultaneously for following command:
call cfx run
But I know it's executing because firefox window pops up. I get all the output suddenly when I execute proc.destroy();
This is my bat file:
#echo off
call %1
cd C:\Users\Madhawa.se\Desktop\workingfox\beauty
call cfx run
pause
This is my Java code:
Thread t = new Thread(new Runnable() {
#Override
public void run() {
try {
Runtime rt = Runtime.getRuntime();
String[] commands = {"C:\\Users\\Madhawa.se\\Desktop\\workingfox\\runner\\foxrun.bat", "C:\\mozilla-build\\addon-sdk-1.16\\bin\\activate.bat"};
proc = rt.exec(commands);
BufferedReader stdInput = new BufferedReader(new InputStreamReader(proc.getInputStream()));
BufferedReader stdError = new BufferedReader(new InputStreamReader(proc.getErrorStream()));
// read the output from the command
String s = null;
while ((s = stdInput.readLine()) != null) {
System.out.println(s);
}
// read any errors from the attempted command
while ((s = stdError.readLine()) != null) {
System.out.println(s);
}
proc.waitFor();
System.out.println("success");
} catch (Exception ex) {
ex.printStackTrace();
}
}
});
t.start();
How to get output immediately and why it acts differently for this command?
i was able to fix it using process builder instead of runtime.exec .and inheriteIo doesn't work .it blocks the realtime output
Thread t = new Thread(new Runnable() {
private String s;
#Override
public void run() {
try {
Component selectedComponent = jTabbedPane2.getSelectedComponent();
if (selectedComponent instanceof MyTextArea) {
String response = "";
System.out.println("yes");
MyTextArea temptextarea = (MyTextArea) selectedComponent;
String xpiPath = new File(temptextarea.getNameX()).getParentFile().getPath();
String[] commands = {"C:\\Users\\Madhawa.se\\Desktop\\workingfox\\runner\\foxrun.bat", "C:\\mozilla-build\\addon-sdk-1.16\\bin\\activate.bat
ProcessBuilder process = new ProcessBuilder(commands);
process.redirectErrorStream(true);
Process shell = process.start();
//shell.waitFor();
BufferedReader stdInput = new BufferedReader(new InputStreamReader(shell.getInputStream()));
BufferedReader stdError = new BufferedReader(new InputStreamReader(shell.getErrorStream()));
// read the output from the command
System.out.println("Here is the standard output of the command:\n");
while ((s = stdInput.readLine()) != null) {
System.out.println("s:" + s);
}
// read any errors from the attempted command
System.out.println("Here is the standard error of the command (if any):\n");
while ((s = stdError.readLine()) != null) {
System.out.println("w:" + s);
}
}
} catch (Exception ex) {
ex.printStackTrace();
}

executing a java program in another java program using Runtime.exec() function

The following code snippet i had given is using exec function and executes hello program (simple "hello world" printing java program). But as soon as i execute the main program, print statement of instream.readline() simply returns NULL. Please try to sort out the problem. Hope the explanation is clear.
CODE:
Process process2=null;
BufferedReader inStream=null;
try
{
process2 = Runtime.getRuntime().exec("java hello");
}
catch(IOException e1)
{
System.err.println("Error on exec method");
e1.printStackTrace();
}
try
{
inStream = new BufferedReader(new InputStreamReader(process2.getInputStream() ));
System.out.println(inStream.readLine());
}
catch(IOException e1)
{
System.err.println("Error on inStream.readLine()");
e1.printStackTrace();
}
First of all your hello.java should be already compiled n the class file should present in the current directory where the program is located.
And for getting errors, you can get error stream from process class's object.
BufferedReader stdError = new BufferedReader(new InputStreamReader(pr.getErrorStream()));
String s="";
while ((s = stdError.readLine()) != null)
System.out.println(s);
Working with Eclipse/java7/windows
import java.io.BufferedReader;
import java.io.InputStreamReader;
public class ProcessDemo {
public static void main(String[] args) throws Exception {
final String dir = System.getProperty("user.dir");
System.out.println("current dir = " + dir);
Runtime run = Runtime.getRuntime();
Process pr=run.exec("javac -d "+ dir +"\\src "+ dir+"\\src\\HelloDemo.java");
pr.waitFor();
BufferedReader stdError = new BufferedReader(new InputStreamReader(pr.getErrorStream()));
BufferedReader buf = new BufferedReader(new InputStreamReader(pr.getInputStream()));
String line = "";
String s;
// read any errors from the attempted command
System.out.println("Here is the standard error of the command (if any):\n");
while ((s = stdError.readLine()) != null)
System.out.println(s);
//read output
while ((line=buf.readLine()) != null)
System.out.println(line);
pr.destroy();
Runtime run1 = Runtime.getRuntime();
Process pr1=run1.exec("java -cp "+dir+"\\src HelloDemo");
BufferedReader stdError1 = new BufferedReader(new InputStreamReader(pr1.getErrorStream()));
BufferedReader buf1 = new BufferedReader(new InputStreamReader(pr1.getInputStream()));
//interpretting file n executing it line by line :D :P
pr1.waitFor();
String temp;
// read any errors from the attempted command
System.out.println("\n\nHere is the standard error of the command (if any):\n");
while ((temp = stdError1.readLine()) != null)
System.out.println(temp);
//read output
System.out.println(buf1.readLine());
while ((temp=buf1.readLine()) != null)
System.out.println(temp);
}
}

Java Process cannot get the InputStream through Runtime.getRunTime().exec()

try {
String str;
Process process = Runtime.getRuntime().exec("bash /home/abhishek/workspace/Pro/run");
InputStream isout = process.getInputStream();
InputStreamReader isoutr = new InputStreamReader(isout);
BufferedReader brout = new BufferedReader(isoutr);
while ((str = brout.readLine()) != null) {
System.out.println(str);
}
} catch (IOException e) {
e.printStackTrace();
}
The Code has issues with getting the InputStream from the Process,
because if I run the Shell script from my Terminal it runs completely fine,
but if I Run the Script like this,the str is always null,
I am using this code to get the output of the Shell Script directly into Java instead writing the Script Output in the File
Is there any other way to achieve this,or how can I get the issue solved using the current approach
I think something returned through the error stream, so you can try to check something from the Process.getErrorStream().
You should also wait for the created process to prevent your main program completes before it. Use Process.waitFor();
public class TestMain {
private static final String BASH_CMD = "bash";
private static final String PROG = "/home/abhishek/workspace/Pro/run";
private static final String[] CMD_ARRAY = { BASH_CMD , PROG };
public static void main(String[] args) {
new Thread(new Runnable() {
public void run() {
BufferedReader reader = new BufferedReader(new InputStreamReader(
System.in));
String command = null;
try {
while ((command = reader.readLine()) != null) {
System.out.println("Command Received:" + command);
}
} catch (Exception ex) {
ex.printStackTrace();
// failed to listening command
}
}
}).start();
Process process = null;
try {
ProcessBuilder processBuilder = new ProcessBuilder(CMD_ARRAY);
process = processBuilder.start();
InputStream inputStream = process.getInputStream();
setUpStreamGobbler(inputStream, System.out);
InputStream errorStream = process.getErrorStream();
setUpStreamGobbler(errorStream, System.err);
System.out.println("never returns");
process.waitFor();
} catch (IOException e) {
throw new RuntimeException(e);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
public static void setUpStreamGobbler(final InputStream is, final PrintStream ps) {
final InputStreamReader streamReader = new InputStreamReader(is);
new Thread(new Runnable() {
public void run() {
BufferedReader br = new BufferedReader(streamReader);
String line = null;
try {
while ((line = br.readLine()) != null) {
ps.println("process stream: " + line);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}).start();
}
}
Edit you /home/abhishek/workspace/Pro/run if it is a shell and add the following line on top.
#!/usr/bin/bash
and give required execute permissions to /home/abhishek/workspace/Pro/run.
Then use the following line
Process process = Runtime.getRuntime().exec("/home/abhishek/workspace/Pro/run");
Now if the run program prints anything you should see it in the output.
Your code looks fine. So, I believe that problem is either in command line you are using (bash /home/abhishek/workspace/Pro/run) or in your script itself.
I'd suggest you to perform the following steps:
try to run some well-known command instead of your script. For example pwd. Check that your code that is reading from input stream works correctly.
Now try to simplify your script. Create script run1 that just runs the same pwd. Now run this script from java and see that it is working. BTW you do not have to run it as bash yourscript. You can directly run it without bash prefix
If all this works start to move from simple to your real script step-by-step. I believe you will find your mistake. Probably your script cannot start for some environment related problems.
Possible problem is by the time you obtain inputStram the sub-process is not ready
Try
Process process = Runtime.getRuntime().exec("bash /home/abhishek/workspace/Pro/run");
InputStream isout = process.getInputStream();
process.waitFor()
Try something like this:
String[] runCommand = new String[3];
runCommand[0] = "sh";
runCommand[1] = "-c";
runCommand[2] = "bash /home/abhishek/workspace/Pro/run";
Process process = runtime.exec(runCommand);
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line = reader.readLine();
reader.close();
After multiple readings of the source code for the unix implementation of Process at https://github.com/AdoptOpenJDK/openjdk-jdk11/blob/master/src/java.base/unix/classes/java/lang/ProcessImpl.java it seems that the standard redirects will always swallow to a ProcessBuilder.NullInputStream:
if (redirects[1] == Redirect.PIPE) {
std_fds[1] = -1;
}...
and
stdout = (fds[1] == -1 || forceNullOutputStream) ?
ProcessBuilder.NullInputStream.INSTANCE :
new ProcessPipeInputStream(fds[1]);
(The same code repeats for stdIn, stdOut and stdErr streams)
The only workaround I have found, which feels very clumsy is to use a temp File:
File stdOutTmp; // create and destroy however you see fit
ProcessBuilder pb = ...;
pb.redirectOutput(ProcessBuilder.Redirect.to(stdOutTmp));
...
There are other static factory methods (Redirect.appendTo(File) to append to an existing file rather than overwrite an existing file, and Redirect.from(File) for stdIn)

How to Execute Windows Commands Using Java - Change Network Settings

In Java, I want to be able to execute a Windows command.
The command in question is netsh. This will enable me to set/reset my IP address.
Note that I do not want to execute a batch file.
Instead of using a batch file, I want to execute such commands directly. Is this possible?
Here is my implemented Solution for Future Reference:
public class JavaRunCommand {
private static final String CMD =
"netsh int ip set address name = \"Local Area Connection\" source = static addr = 192.168.222.3 mask = 255.255.255.0";
public static void main(String args[]) {
try {
// Run "netsh" Windows command
Process process = Runtime.getRuntime().exec(CMD);
// Get input streams
BufferedReader stdInput = new BufferedReader(new InputStreamReader(process.getInputStream()));
BufferedReader stdError = new BufferedReader(new InputStreamReader(process.getErrorStream()));
// Read command standard output
String s;
System.out.println("Standard output: ");
while ((s = stdInput.readLine()) != null) {
System.out.println(s);
}
// Read command errors
System.out.println("Standard error: ");
while ((s = stdError.readLine()) != null) {
System.out.println(s);
}
} catch (Exception e) {
e.printStackTrace(System.err);
}
}
}
Runtime.getRuntime().exec("netsh");
See Runtime Javadoc.
EDIT: A later answer by leet suggests that this process is now deprecated. However, as per the comment by DJViking, this appears not to be the case: Java 8 documentation. The method is not deprecated.
Use ProcessBuilder
ProcessBuilder pb=new ProcessBuilder(command);
pb.redirectErrorStream(true);
Process process=pb.start();
BufferedReader inStreamReader = new BufferedReader(
new InputStreamReader(process.getInputStream()));
while(inStreamReader.readLine() != null){
//do something with commandline output.
}
You can run the command with Runtime.getRuntime().exec("<command>") (eg. Runtime.getRuntime().exec("tree")). But, this will only run executables found in path, not commands like echo, del, ... But only stuff like tree.com, netstat.com, ... To run regular commands, you will have to put cmd /c before the command (eg Runtime.getRuntime().exec("cmd /c echo echo"))
public static void main(String[] args) {
String command="netstat";
try {
Process process = Runtime.getRuntime().exec(command);
System.out.println("the output stream is "+process.getOutputStream());
BufferedReader reader=new BufferedReader( new InputStreamReader(process.getInputStream()));
String s;
while ((s = reader.readLine()) != null){
System.out.println("The inout stream is " + s);
}
} catch (IOException e) {
e.printStackTrace();
}
}
This works.
Runtime#exec().

Categories

Resources