您的位置:首页 > 编程语言 > Java开发

java 调用其它程序

2013-06-05 16:12 204 查看
假设我们已经把以下的 C 程序编绎成 adder.exe:

#include <stdio.h>

int main() { /* 简单地循环打印标准输入上的两个整数之和 */

int a, b, lineNumber = 0;

while (scanf("%d %d", &a, &b))

printf("Line# %d \t %d + %d == %d\n", ++lineNumber, a, b, a + b);

return 0;

}

以下的 Java 程序可以在启动 adder.exe 后,跟 adder.exe 的标准输入和输出接轨,然后持续不断地向

它发送数据和索取结果:

import java.io.*;

class C {

public static void main(String[] args) throws Exception {

final Process proc = Runtime.getRuntime().exec("adder.exe");

// 用另一个线程把参数送到 proc 的标准输入上去。

new Thread() {

public void run() {

OutputStream stdin = proc.getOutputStream();

for (int i = 0; ; i++) {

try {

Thread.sleep(1); // 要休息片刻才看得到 I/O 的缓存效果。

stdin.write((i + " " + i + "\n").getBytes());

} catch (Exception ex) {

ex.printStackTrace();

}

}

}

}.start();

// 主线程负责读取并打印 proc 的标准输出。

BufferedReader stdout = new BufferedReader(new InputStreamReader

(proc.getInputStream()));

for (String line; null != (line = stdout.readLine()); )

System.out.println(line);

}

}

循环里的 Thread.sleep(1) 纯粹是为了凸显 I/O 的缓存效果。

我测试时看到大约 900 行的缓存量(用 32-bit XP 和 Java 1.6)。

有时候,需要在Java中调用现成的.exe文件或是cmd进行操作,下面结合自己的项目实例,做以小结。

现在我们的目标是:用Java调用cmd,执行C:/libsvm/windows/svm-train.exe,svm-train.exe参数为:

[options] training_set_file [model_file]

具体是 -c 32 -g 0.0078125 trainset trainset.model

可以将doc窗口的输出显示到JAVA IDE的控制台上。

我们需要用到java.lang.Runtime类

主要成员函数:

getRuntime() 返回与当前 Java 应用程序相关的运行时对象。

Runtime r=Runtime.getRuntime();

exec(String command, String[] envp, File dir) 在有指定环境和工作目录的独立进程中执行指定的字

符串命令。 。command为.exe及其参数,envp null即可,dir=new File(FilePath)

java.lang.Process类

主要成员函数:

waitFor() 导致当前线程等待,如果必要,一直要等到由该 Process 对象表示的进程已经终止。

注:Process p = Runtime.getRuntime().exec(arg)

实现代码如下:

[java] view
plaincopy

public static void main(String[] args) {

try {

Runtime r = Runtime.getRuntime();

String[] cmd = new String[5];

cmd[0] = "cmd "; //命令行

cmd[1] = "/c "; //运行后关闭,

cmd[2] = "start "; //启动另一个窗口来运行指定的程序或命令(cmd 命令集里的)

cmd[3] = "C:\\windows"; //要运行的.exe程序的目录

cmd[4] = "svm-train -c 32 -g 0.0078125 -v 5 trainset ";//exe程序及其需要的参数

String Naiveexe = "calc.exe";//windows自带计算器

String line;

String space=" ";

//Process p = Runtime.getRuntime().exec("cmd /c svm-train.exe -c 32 -g 0.0078125 -v 5 trainset",null,new File("C:\\libsvm\\windows")); 此时输出到控制台

//Process p = Runtime.getRuntime().exec("cmd /c start svm-train.exe -c 32 -g 0.0078125 -v 5 trainset",null,new File("C:\\libsvm\\windows"));此时弹出dos窗口运行

Process p = Runtime.getRuntime().exec((cmd[0]+cmd[1]+cmd[4]),null,new File(cmd[3]));

//Process p = Runtime.getRuntime().exec("calc.exe"); //直接运行计算器

BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));

while((line=br.readLine()) != null){

System.out.println(line);

//p.waitFor();

}

} catch (IOException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

http://hi.baidu.com/469741414/blog/item/8b5a8289e22817dafd1f1086.html

使用Runtime.getRuntime().exec()方法可以在java程序里运行外部程序.

该方法有6个可访问版本:

1.exec(String command)

2.exec(String command, String envp[], File dir)

3.exec(String cmd, String envp[])

4.exec(String cmdarray[])

5.exec(String cmdarray[], String envp[])

6.exec(String cmdarray[], String envp[], File dir)

一般的应用程序可以直接使用第一版本,当有环境变量传递的时候使用后面的版本.

其中2和6版本可以传递一个目录,标识当前目录,因为有些程序是使用相对目录的,所以就要使用这个版本.

当要执行批处理的时候,不能直接传递批处理的文件名,而要使用:

cmd.exe /C start 批处理文件名

使用dos命令(比如dir)时也要使用掉调用.

如果想与调用的程序进行交互,那么就要使用该方法的返回对象Process了,通过Process的getInputStream(),getOutputStream(),getErrorStream()方法可以得到输入输出流,然后通过InputStream可以得到程序对控制台的输出信息,通过OutputStream可以给程序输入指令,这样就达到了程序的交换功能.

例子如下:

[java] view
plaincopy

import java.io.BufferedReader;

import java.io.IOException;

import java.io.InputStreamReader;

import java.io.OutputStreamWriter;

import java.io.PrintWriter;

public class ExecuteTask implements Runnable {

private boolean isRunning = true;

public ExecuteTask() {

}

public void run() {

}

public static void main(String[] args) {

try {

Process proc = Runtime.getRuntime().exec("cmd.exe");

BufferedReader read = new BufferedReader(new InputStreamReader(

proc.getInputStream()));

new Thread(new Echo(read)).start();

PrintWriter out = new PrintWriter(new OutputStreamWriter(

proc.getOutputStream()));

BufferedReader in = new BufferedReader(new InputStreamReader(

System.in));

String instr = in.readLine();

while (!"exit".equals(instr)) {

instr = in.readLine();

out.println(instr);

// file: // out.println("telnet 192.168.0.1");

out.flush();

}

in.readLine();

read.close();

out.close();

} catch (IOException ex) {

ex.printStackTrace();

}

}

}

class Echo implements Runnable {

private BufferedReader read;

public Echo(BufferedReader read) {

this.read = read;

}

public void run() {

try {

String l = read.readLine();

while (l != null) {

System.out.println(l);

l = read.readLine();

}

System.out.println("---执行完毕:");

} catch (IOException ex) {

ex.printStackTrace();

}

}

}

/article/9655043.html

今天遇到了个奇怪的问题,用VC写了个小程序,编译成exe文件,然后用Java去调,居然卡住不运行了。

如果双击这个exe程序,单独让它运行,是可以的,那么为什么用Java调用就不好使了呢?

上网查了一下,原来是由于缓冲区的问题,也就是说Process的getErrorStream和getInputStream缓冲区没有清空。我在VC里要打印的东西太多了,以至于填满了缓冲区,这是缓冲区需要释放,我不但没释放还一个劲的运行程序,那么Java就卡在那里了。表面上好像是exe出了问题,其实是这个Process的缓冲区造成的。

解决方法:

InputStream is1 = process.getInputStream();

BufferedReader br = new BufferedReader(new InputStreamReader(is1));

try {

while(br.readLine() != null) ;

} catch (IOException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

InputStream is2 = process.getErrorStream();

if(null != is2) {

BufferedReader br2 = new BufferedReader(new InputStreamReader(is2));

StringBuilder buf = new StringBuilder(); // 保存输出结果流

String line = null;

try {

while(br2.readLine() != null) ;

buf.append(line);

} catch (IOException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

System.out.println("输出结果为:" + buf.toString(());

}

将上述代码加入程序就可以解决缓冲区的问题,建议单独开启线程去多。

我的代码里不需要getErrorStream()部分的代码,这两部分针对实际情况自由选择。

http://blog.sina.com.cn/s/blog_59c701350100q9l9.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: