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

来源:互联网 发布:聚财网络 编辑:程序博客网 时间:2024/06/16 19:10

很多时候,我们往往需要在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.BufferedWriter;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)

测试结果:

hellowrite1xx9write239.5---------------------null

当然,由于进程或者脚本等待着输入,而java迟迟不给输出,那么java的子线程stin,sterr也不会结束,我们将得不到脚本或进程的输出,而是得到null.此处,我没有设置抛出异常,而是把stin,sterr设置为了后台线程,当主线程结束,stin,sterr也随之终止,process也随之destroy掉,避免进程或脚本一直等待输入而持续运行.

1 0
原创粉丝点击