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

java调用脚本语言或其他进程(以Python为例)

2017-04-07 01:30 543 查看
很多时候,我们往往需要在java中调用其他脚本语言,或者是其他进程,来弥补java的一些不便之处.

万能的方式就是使用Process类了,当然针对Python还可以使用jython,但jython还是有诸多不便

String command = "python test.py";
Process pythonProcess = Runtime.getRuntime().exec(command);


Process的强大功能,就在于调用其他进程时,可以相互实现信息传递,基于java IO实现,调用者只需要熟悉java IO操作,即可调用.

我写了一个辅助类,以便于对进程之间的信息传递,实现策略为,将InputStream操作改为线程操作.具体代码如下:

package runtime;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
/**
* 将InputStream操作改为线程操作
*/
public class StreamThreadRead extends Thread{
//存储读取的字符串
private final StringBuffer sBuffer;
//对应的输入流
private final InputStream iStream;
public StreamThreadRead(InputStream iStream){
super();
sBuffer = new StringBuffer();
this.iStream = iStream;
}
@Override
public void run() {
BufferedReader bReader = new BufferedReader(new InputStreamReader(iStream));
String str;
try {
while ((str = bReader.readLine()) != null) {
sBuffer.append(str).append("\n");
}
} catch (IOException e) {
e.printStackTrace();
}
}
public StringBuffer getsBuffer() {
return sBuffer;
}
public InputStream getiStream() {
return iStream;
}
}


这个便是辅助类啦,类如其名”进程IO传输”,不过准确来讲,已经实现进程简单管理了.

可以随心所欲的在java和脚本之间传递数据,贼爽啊!

package runtime;

import java.io.BufferedWri
4000
ter;
import java.io.IOException;
import java.io.OutputStreamWriter;

/**
* 进程数据传输对象
*/
public class ProcessIOTransport {
private final BufferedWriter stout;
private final StreamThreadRead stin;
private final StreamThreadRead errin;
private final Process process;

/**
* 构造一个ProcessIOTransport
* @param process
* @throws IOException
*/
public ProcessIOTransport(String command) throws IOException{
process = Runtime.getRuntime().exec(command);
stout = new BufferedWriter(new OutputStreamWriter(process.getOutputStream()));
stin = new StreamThreadRead(process.getInputStream());
errin = new StreamThreadRead(process.getErrorStream());
//设为后台线程
stin.setDaemon(true);
errin.setDaemon(true);
//启动线程
stin.start();
errin.start();
//监控进程
new Thread(new Runnable(){
@Override
public void run() {
while(stin.isAlive()||errin.isAlive()){
try {
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
process.destroy();
}
});
}
/**
* 构造一个ProcessIOTransport,其中向进程中输入参数args
* @param process
* @param args
* @throws IOException
*/
public ProcessIOTransport(String command,String...args) throws IOException{
this(command);
write(args);
}
/**
* 构造一个ProcessIOTransport,当前java线程等待进程运行结束
* @param process
* @param timeOut 最迟等待时间(ms)
* @throws IOException
*/
public ProcessIOTransport(String command,long timeOut) throws IOException{
this(command,timeOut,new String[]{null});
}
/**
* 构造一个ProcessIOTransport,当前java线程等待进程运行结束
* @param process
* @param timeOut 最迟等待时间(ms)
* @param args 向进程中传入的参数
* @throws IOException
*/
public ProcessIOTransport(String command,long timeOut,String...args) throws IOException{
this(command,args);
long start = System.currentTimeMillis();
long now = System.currentTimeMillis();
while(now-start<timeOut&&(stin.isAlive()||errin.isAlive())){
try {
Thread.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
now = System.currentTimeMillis();
}
}

/**
* 向process写数据
* @param args
* @throws IOException
*/
public void write(String...args) throws IOException {
for(int i = 0;i<args.length;i++){
if(args[i]!=null){
stout.write(args[i]);
stout.flush();
}
}
}
/**
* 读取process的标准输出
* @return
*/
public String readStandard(){
if(stin.isAlive()){
return null;
}else{
return stin.getsBuffer().toString();
}
}
/**
* 读取process的错误输出
* @return
*/
public String readError(){
if(stin.isAlive()){
return null;
}else{
return stin.getsBuffer().toString();
}
}
}


最后我们测试一下吧:

package runtime;

import java.io.IOException;

public class Test {

public static void main(String[] args) {
String command = "python test.py";
try {
ProcessIOTransport piot1 = new ProcessIOTransport(command,200,"write1\n","write2\n");
ProcessIOTransport piot2 = new ProcessIOTransport(command,200,"write3\n");
System.out.println(piot1.readStandard());
System.out.println("---------------------");
System.out.println(piot2.readStandard());
} catch (IOException e) {
e.printStackTrace();
}
}

}


测试的Python代码如下

#unicode=UTF-8
print ('hello')
v = input()
print (v)
print ('xx')
print (3+6)
z = input()
print (z)
print (3+3+3+3+3+3+3+3+3+3/6+3+3+3+3)


测试结果:

hello
write1
xx
9
write2
39.5

---------------------
null


当然,由于进程或者脚本等待着输入,而java迟迟不给输出,那么java的子线程stin,sterr也不会结束,我们将得不到脚本或进程的输出,而是得到null.此处,我没有设置抛出异常,而是把stin,sterr设置为了后台线程,当主线程结束,stin,sterr也随之终止,process也随之destroy掉,避免进程或脚本一直等待输入而持续运行.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: