Java调用系统命令学习(二)

经过上一篇的学习,应该对Java中的Runtime类的exec方法了大致的了解,也知道应该如何去使用了吧。

首先学习下:Process类。

简单地测试一下:

调用Javac命令,并查看执行命令的返回值,并输出到控制台上去。
import java.io.IOException;
class Exec_Javac{
public static void main(String []args)throws IOException{
Runtime rt = Runtime.getRuntime();
Process p = rt.exec("javac");
int exitValue = p.exitValue();
System.out.println("Process exitValue="+exitValue);
}
}
//执行结果:
Exception in thread "main" java.lang.IllegalThreadStateException: process hasn't exited
at java.lang.UNIXProcess.exitValue(UNIXProcess.java:172)
at Exec_Javac.main(Exec_Javac.java:6)


呵呵,从上面,我们可以知道,并不能得到我们想要的结果。至于什么原因呢。

下面一段话直接引用别人的:(它比较详细地讲述了出错的原因)

[b][color=blue]这里主要的问题就是错误的调用了exitValue来取得外部命令的返回值(呵呵,这个错误我也曾经犯过),因为 exitValue这个方法是不阻塞的,程序在调用这个方法时外部命令并没有返回所以造成了异常的出现,这里是由另外的方法来等待外部命令执行完毕的,就是waitFor方法,这个方法会一直阻塞直到外部命令执行结束,然后返回外部命令执行的结果,作者在这里一顿批评设计者的思路有问题,呵呵,反正我是无所谓阿,能用就可以拉。但是作者在这里有一个说明,就是exitValue也是有好多用途的。因为当你在一个Process上调用waitFor方法时,当前线程是阻塞的,如果外部命令无法执行结束,那么你的线程就会一直阻塞下去,这种意外会影响我们程序的执行。所以在我们不能判断外部命令什么时候执行完毕而我们的程序还需要继续执行的情况下,我们就应该循环的使用exitValue来取得外部命令的返回状态,并在外部命令返回时作出相应的处理。 [/color][/b]

那么好,既然出错了,当然要修改啦:

改为如下:
import java.io.IOException;
class Exec_Javac{
public static void main(String []args)throws IOException,InterruptedException{
Runtime rt = Runtime.getRuntime();
Process p = rt.exec("javac");
//int exitValue = p.exitValue();
int exitValue = p.waitFor();
System.out.println("Process exitValue="+exitValue);
}
}
//执行结果为
Process exitValue=2 

得到上面这个结果是我意想不到的。因为在Windows下执行,会一直阻塞在那里。

却我在Ubuntu里面执行时,却在编译时却却不过,

抛出了这样的异常:

Exec_Javac.java:7: unreported exception java.lang.InterruptedException; must be caught or declared to be thrown
int exitValue = p.waitFor();
^
1 error

后来加上InterrupedException才可以执行。可以是环境上的不同。虽然是输出了结果,但是因为异常中断才输出的结果。也不是我想要的结果。这个又是为什么呢?

以下又是引用别人的话:

[b][color=red]JDK文档中对此有如此的解释:因为本地的系统对标准输入和输出所提供的缓冲池有效,所以错误的对标准输出快速的写入和从标准输入快速的读入都有可能造成子进程的锁,甚至死锁。 [/color][/b]


文档引述完了,作者又开始批评了,他说JDK仅仅说明为什么问题会发生,却并没有说明这个问题怎么解决,这的确是个问题哈。紧接着作者说出自己的做法,就是在执行完外部命令后我们要控制好Process的所有输入和输出(视情况而定),在这个例子里边因为调用的是 Javac,而他在没有参数的情况下会将提示信息输出到标准出错,所以在下面的程序中我们要对此进行处理。

呵呵。。不是想要的结果。当然还是得改进啦。

代码如下:
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader ;
import java.io.BufferedReader;
class Exec_Javac{
public static void main(String []args)throws IOException,InterruptedException{
Runtime rt = Runtime.getRuntime();
Process p = rt.exec("javac");
//int exitValue = p.exitValue();
//int exitValue = p.waitFor();
InputStream is = p.getErrorStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String line = null;
System.out.println("<ERROR>");
while((line = br.readLine())!=null){
System.out.println(line);
System.out.println("</ERROR>");
int exitValue = p.waitFor();
System.out.println("Process exitValue="+exitValue);
}
}
}
//执行结果:
<ERROR>
Usage: javac <options> <source files>
</ERROR>
Process exitValue=2
where possible options include:
</ERROR>
Process exitValue=2
-g Generate all debugging info
</ERROR>
Process exitValue=2
-g:none Generate no debugging info
</ERROR>
Process exitValue=2
-g:{lines,vars,source} Generate only some debugging info
</ERROR>
Process exitValue=2
-nowarn Generate no warnings
</ERROR>
Process exitValue=2
-verbose Output messages about what the compiler is doing
</ERROR>
Process exitValue=2
-deprecation Output source locations where deprecated APIs are used
</ERROR>
Process exitValue=2
-classpath <path> Specify where to find user class files and annotation processors
</ERROR>
Process exitValue=2
-cp <path> Specify where to find user class files and annotation processors
</ERROR>
Process exitValue=2
-sourcepath <path> Specify where to find input source files
</ERROR>
Process exitValue=2
-bootclasspath <path> Override location of bootstrap class files
</ERROR>
Process exitValue=2
-extdirs <dirs> Override location of installed extensions
</ERROR>
Process exitValue=2
-endorseddirs <dirs> Override location of endorsed standards path
</ERROR>
Process exitValue=2
-proc:{none,only} Control whether annotation processing and/or compilation is done.
</ERROR>
Process exitValue=2
-processor <class1>[,<class2>,<class3>...]Names of the annotation processors to run; bypasses default discovery process
</ERROR>
Process exitValue=2
-processorpath <path> Specify where to find annotation processors
</ERROR>
Process exitValue=2
-d <directory> Specify where to place generated class files
</ERROR>
Process exitValue=2
-s <directory> Specify where to place generated source files
</ERROR>
Process exitValue=2
-implicit:{none,class} Specify whether or not to generate class files for implicitly referenced files
</ERROR>
Process exitValue=2
-encoding <encoding> Specify character encoding used by source files
</ERROR>
Process exitValue=2
-source <release> Provide source compatibility with specified release
</ERROR>
Process exitValue=2
-target <release> Generate class files for specific VM version
</ERROR>
Process exitValue=2
-version Version information
</ERROR>
Process exitValue=2
-help Print a synopsis of standard options
</ERROR>
Process exitValue=2
-Akey[=value] Options to pass to annotation processors
</ERROR>
Process exitValue=2
-X Print a synopsis of nonstandard options
</ERROR>
Process exitValue=2
-J<flag> Pass <flag> directly to the runtime system
</ERROR>
Process exitValue=2
</ERROR>
Process exitValue=2

哎,不管怎么说还是出来了结果,作者作了一下总结,就是说,为了处理好外部命令大量输出的情况,你要确保你的程序处理好外部命令所需要的输入或者输出。

其实呀。还有其他,下篇再讲啦。


这会总算得到结果啦。不过在ubuntu里面跟在windows里面得到的结果有点不一样。

大家注意下。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值