import java io *public class CommandWrapper{Process processThread inThread outpublic CommandWrapper(Process process){this process = processfinal InputStream inputStream =process getInputStream()//final BufferedReaderr=new BufferedReader(new InputStreamReader(inputStream))final byte[] buffer = new byte[ ]out = new Thread(){//String lineint lineNumber= public void run(){try {while (true){int count = inputStream read(buffer)System out println(lineNumber+ : +new String(buffer count ))//line=r readLine()//System out println(lineNumber+ : +line)lineNumber++}}catch (Exception e){}}}final BufferedReader reader =new BufferedReader(new InputStreamReader(System in))final OutputStreamoutputStream = process getOutputStream()in = new Thread(){String linepublic void run(){try{while (true){outputStream write((reader readLine()+ \n ) getBytes())outputStream flush()}}catch (Exception e){}}}}public void startIn(){in start()}public void startOut(){out start()}public void interruptIn(){in interrupt()}public void interruptOut(){out interrupt()}public static void main(String[] args){try{CommandWrapper mand= new CommandWrapper(Runtime getRuntime() exec( native ascii ))mand startIn()mand startOut()}catch (Exception e){e printStackTrace()}}}我以native ascii为范例
程序和网友给我的那个程序做了对比 发现如下几个在处理这个
问题时需要注意的地方 由于不知道目标程序的输入输出顺序 因此只能建立两个单独的线程分别处理输入和输出 这样输入和输出就不会阻塞了 但是有些目标程序要求有特定的输入输出顺序 而经过这个类封装的结果是在任何状态下都可以输入 程序的任何输出也会被马上反映出来 这是构造通用类的第一个问题 不能直接使用I/O重定向 在最开始的
时候我是考虑直接使用I/O重定向的 但是实际的情况是Process的I/O的定义刚好和我的预想相反 我们从Process取得的InputStream实际上是它的输出 而取得的OutputStream是它的输入 这样就无法进行I/O重定向了 必须我们进行编码来读取程序的输出和写入控制台的输入 (这里的I/O重定向是指想将它的I/O直接重定向到系统的I/O) 写入控制台的输入 outputStream write((reader readLine()+ \n ) getBytes())outputStream flush()这里有两个问题值得注意 第一个是我们在控制台输入一行数据以后按下回车 那么语句reader readLine()可以正确的得到你的输入 为什么要加那个换行符呢?这是在测试的时候发现的问题 在以native ascii作为例子的时候发现不加这个的话它不能得到控制台的输入 但是我在替那位网友解决的问题的时候他的程序则没有这个问题 因此猜想可能是因为有的程序要求读取的一整行的数据(例如native ascii) 而大部分的命令行程序在编码的时候读取的是整数这样的值或者其他类型的值 他们是以空格或者其他的字符分隔的 因此就不需要那个额外的换行符(例如那位网友的程序读取的是一元二次方程的三个系数) 另外一个问题就是flush方法的使用 在最开始的时候没有想到要这样刷新进去 无论是否加换行符外部程序都无法读取写入的输入 后来才想到要调用一下这个方法 这个也是在我们输出的时候应该注意的一个问题 有些需要马上反应出来的输出一般都在写入以后要调用它 否则输出/输入不能马上反应出来 对于程序的输出 最开始我是构造的一个BufferedReader想以行为单位输出 对于那位网友的程序 结果证明不是很好用 但是以native ascii作为例子运行又没有问题 这个估计和外部程序的代码也有关系 如果外部程序没有输出换行符可能使用BufferedReader就会有问题 但是通过直接读取输出就没有问题了 另外需要注意的就是 System out println(lineNumber+ : +new String(buffer count ))中严格来说应该是 System out println(lineNumber+ : +new String(buffer count))之所以减一是因为读取输入的时候人为的多加了一个换行符 如果这个地方不减一就会多输出一个空行 基于以上的种种原因 要构造一个执行外部程序的包装器类不太好办 特别是文章中提到的几个问题 有时间和兴趣的朋友可以做一下测试 看看以上的问题和猜测是否正确 另外附上一段源代码 是一个fortran的程序 implicit nonereal a b creal dreal root root print* 请输入一元二次方程的系数a b c: read(* *) a b cd=b** *a*cif(d>= ) thenroot =( b+sqrt(d))/( *a)root =( b sqrt(d))/( *a)print* root = root print* root = root elseprint* 一元二次方程没有实根! end ifpauseend lishixinzhi/Article/program/Java/JSP/201311/19704
调用外部程序接口
方法1.
Process p=Runtime.getRuntime.exec("cmd")(最常用)
方法2.
Process p=new ProcessBuilder(cmd).start()
但是一般方法一比较常用, 下面我们介绍下方法一中关于抽象Process类的常用函数
//向对应程序中输入数据
abstract public OutputStream getOutputStream()
//获得对应程序的输出流(没写错)
abstract public InputStream getInputStream()
//获得程序的错误提示
abstract public InputStream getErrorStream()
//等待程序执行完成,返回0正常,返回非0失败
abstract public int waitFor() throws InterruptedException
//获得程序退出值,0正常退出,非0则异常
abstract public int exitValue()
//销毁进程
abstract public void destroy()
其中前3个函数用的最多
评论列表(0条)