
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
用Runtime.getRuntime().exec()方法可以在java程序里运行外部程序。
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版本可以传递一个目录,标识当前目录,因为有团咐手些程序是使用相对目录的,所以就要使用这个版本。
实例:
Process process = Runtime.getRuntime().exec(".\\p.exe")
process.waitfor()
在上面的程序中,第一行的“.\\p.exe”是要执行的程序名,Runtime.getRuntime()返回当前应用程序的Runtime对象,该对象的exec()方法指示Java虚拟机创建一个子进程执行指定的可执行程序,并返回与该子进程对应的Process对象实例。通过Process可以控制该子进程的执行或获取该子进程的信塌嫌息。第二条语句的目的等待子进程完成再简迟往下执行。
用Runtime.getRuntime().exec()方法,方法的参数传一个字符串,表示外部程序的exe文件的路径。(Runtime类在java.lang包下,所以尘悉不需要另添加敬扒import语句。)例如你要运行D盘根目录下的test.exe程序,就用下面这个语句:Runtime.getRuntime().exec("D:\\test.exe"亮兄昌)这样就可以打开外部程序了。
评论列表(0条)