I want to execute a external .exe program from within java. The .exe is a CLI application which takes input in runtime( scanf() ) and outputs depending on the input. I can call the program to execute from java using
Process p = Runtime.getRuntime().exec("cmd /c start a.exe");
instead of
Process p = Runtime.getRuntime().exec("cmd /c start a.exe");
But I think it is also possible to call a program from within java. I have my whole program written in C++ just need a GUI which is written in java. There are a few things to notice:=
1) The communication with the .exe should be runtime (not through main(args) ) 2) The java program should take the outputs and store in some variable / panel to use for future 3) Program to be executed can differ ( for example user may select a .exe that doesnt take any input at all) ........So basically the java GUI will act as a RuntimeEnv
public void runEXE()
{
String s = null;
try {
Process p = Runtime.getRuntime().exec("cmd /c a.exe");
System.exit(0);
}
catch (IOException e) {
System.out.println("exception happened - here's what I know: ");
e.printStackTrace();
System.exit(-1);
}
}
I know there are a lot of questions about thi开发者_如何学Pythons topic out there. But i cant find any of them much useful.
Rather ugly little function that I use. This takes in the command to be passed to Runtime.getRuntime().exec
, then saves the results into a String, and returns the String at the end. You can pick whether you only want the last line (or all output) and whether you want to save the stdout or stderr string from the process.
private static String systemResult(String cmd, boolean append, boolean useErr)
{
String result = "";
try{
// spawn the external process
//printCmd(cmd);
Process proc = Runtime.getRuntime().exec(cmd);
LineNumberReader lnr1 = new LineNumberReader(new InputStreamReader(proc.getErrorStream()));
LineNumberReader lnr2 = new LineNumberReader(new InputStreamReader(proc.getInputStream()));
String line;
int done = 0;
while(lnr1 != null || lnr2 != null){
try{
if(lnr1.ready()){
if((line = lnr1.readLine()) != null){
//System.err.println("A:" +line);
if(useErr){
if(append) result = result + line + "\n";
else result = line;
}
}
}else if(done == 1){
done = 2;
}
}catch(Exception e1){
try{ lnr1.close(); }catch(Exception e2){}
lnr1 = null;
}
try{
if(lnr2.ready()){
if((line = lnr2.readLine()) != null){
//System.err.println("====>Result: " + line);
if(!useErr){
if(append) result = result + line + "\n";
else result = line;
}
}
}else if(done == 2){
break;
}
}catch(Exception e1){
try{ lnr2.close(); }catch(Exception e2){}
lnr2 = null;
}
try{
proc.exitValue();
done = 1;
}catch(IllegalThreadStateException itsa){}
}
if(lnr1 != null) lnr1.close();
if(lnr2 != null) lnr2.close();
try{
proc.waitFor();
}catch(Exception ioe){
}finally{
try{
proc.getErrorStream().close();
proc.getInputStream().close();
proc.getOutputStream().close();
}catch(Exception e){}
proc = null;
}
}catch(Exception ioe){
}
return result;
}
You could use JNI as @linuxuser27 suggests, or you could use SWIG which helps to make the process of communicating from Java --> C++ a little less painful.
Google Protocol Buffers would be a good option for Java/C++ interoperability.
Protocol buffers are Google's language-neutral, platform-neutral, extensible mechanism for serializing structured data – think XML, but smaller, faster, and simpler. You define how you want your data to be structured once, then you can use special generated source code to easily write and read your structured data to and from a variety of data streams and using a variety of languages – Java, C++, or Python.
I would look at JNI and use some type of IPC to communicate with the C++ project.
Update:
JNI is a way for Java to interface with the underlying native environment the JRE is running on. This method would require you to create a DLL that is loaded into the JRE when your Java program starts. This JNI DLL would then contain a method which could be called from within your Java program that would pass data into the JNI DLL that could then communicate to the C++ project via a named pipe or shared memory.
The named piped would be create using the CreateNamedPipe Win32 API. Within the JNI DLL you would most likely create a server and in the C++ project you would create the client. Note that the server example is multi-threaded but can easily be converted to a single thread model for simplicity.
Note that this is not a simple task. The other answers offer some approaches that are easier, JNA and passing data to the C++ project via stdin.
A couple of things:
- First and foremost, if you haven't done so, read this critically important article: When Runtime.exec won't
- Next, there are several ways for Java to communicate to other applications, and probably the easiest is via standard input and output streams. Have you tried using these?
- Next there's JNI and the easier JNA, but you stated that your C++ program is running via CLI which suggests to me that you have a .NET dll, not a true Windows dll. Is this so? If so, it would make communication between Java and C++ more difficult.
You can execute .exe programs directly. You just need to supply the full path. Relative path will also be ok.
You can use pipes to interface with an external process: Sending Input to a Command, Reading Output from a Command
The solution can be found here Problem getting output and passing input to a executing process running under java
精彩评论