Java调用系统命令学习

view plaincopy to clipboardprint?
import java.io.*;  
class Exec{  
        public static void main(String []args)throws IOException{  
                //Linux系统命令:ls -l  
                String command = "ls -l";  
                //获取当前系统的环境。  
                Runtime rt = Runtime.getRuntime();  
                //执行  
                Process p = null;  
                p = rt.exec(command);  
                //获取执行后的数据  
                BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));  
                String msg = null;  
                //输出。  
                while((msg = br.readLine())!=null){  
                        System.out.println(msg);  
                }  
                br.close();  
        }  
}  
import java.io.*;
class Exec{
        public static void main(String []args)throws IOException{
                //Linux系统命令:ls -l
                String command = "ls -l";
                //获取当前系统的环境。
                Runtime rt = Runtime.getRuntime();
                //执行
                Process p = null;
                p = rt.exec(command);
                //获取执行后的数据
                BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));
                String msg = null;
                //输出。
                while((msg = br.readLine())!=null){
                        System.out.println(msg);
                }
                br.close();
        }

上面的代码比较简单:

其中分为几个步骤:

1.获取当前系统的运行环境。

2.在当前系统执行系统命令。

3.执行后,获取其执行后的数据。

4.输出数据。

5.结束。

========================================================================

首先学习下:Process类。

简单地测试一下:

调用Javac命令,并查看执行命令的返回值,并输出到控制台上去。

  1. import java.io.IOException;   
  2. class Exec_Javac{   
  3.         public static void main(String []args)throws IOException{   
  4.                 Runtime rt = Runtime.getRuntime();   
  5.                 Process p = rt.exec("javac");   
  6.                 int exitValue = p.exitValue();   
  7.                 System.out.println("Process exitValue="+exitValue);   
  8.         }   
  9. }   
  10. //执行结果:   
  11. Exception in thread "main" java.lang.IllegalThreadStateException: process hasn't exited   
  12.     at java.lang.UNIXProcess.exitValue(UNIXProcess.java:172)   
  13.     at Exec_Javac.main(Exec_Javac.java:6)  

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

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

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

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

改为如下:

  1. import java.io.IOException;   
  2. class Exec_Javac{   
  3.         public static void main(String []args)throws IOException,InterruptedException{   
  4.                 Runtime rt = Runtime.getRuntime();   
  5.                 Process p = rt.exec("javac");   
  6.                 //int exitValue = p.exitValue();   
  7.                 int exitValue = p.waitFor();   
  8.                 System.out.println("Process exitValue="+exitValue);   
  9.         }   
  10. }   
  11. //执行结果为   
  12. 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才可以执行。可以是环境上的不同。虽然是输出了结果,但是因为异常中断才输出的结果。也不是我想要的结果。这个又是为什么呢?

以下又是引用别人的话:

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


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

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

代码如下:

  1. import java.io.IOException;   
  2. import java.io.InputStream;   
  3. import java.io.InputStreamReader ;   
  4. import java.io.BufferedReader;   
  5. class Exec_Javac{   
  6.         public static void main(String []args)throws IOException,InterruptedException{   
  7.                 Runtime rt = Runtime.getRuntime();   
  8.                 Process p = rt.exec("javac");   
  9.                 //int exitValue = p.exitValue();   
  10.                 //int exitValue = p.waitFor();   
  11.                 InputStream is = p.getErrorStream();   
  12.                 InputStreamReader isr = new InputStreamReader(is);   
  13.                 BufferedReader br = new BufferedReader(isr);   
  14.                 String line = null;   
  15.                 System.out.println("<ERROR>");   
  16.                 while((line = br.readLine())!=null){   
  17.                         System.out.println(line);   
  18.                         System.out.println("</ERROR>");   
  19.                         int exitValue = p.waitFor();   
  20.                         System.out.println("Process exitValue="+exitValue);   
  21.                 }   
  22.         }   
  23. }   
  24. //执行结果:   
  25. <ERROR>   
  26. Usage: javac <options> <source files>   
  27. </ERROR>   
  28. Process exitValue=2  
  29. where possible options include:   
  30. </ERROR>   
  31. Process exitValue=2  
  32.   -g                         Generate all debugging info   
  33. </ERROR>   
  34. Process exitValue=2  
  35.   -g:none                    Generate no debugging info   
  36. </ERROR>   
  37. Process exitValue=2  
  38.   -g:{lines,vars,source}     Generate only some debugging info   
  39. </ERROR>   
  40. Process exitValue=2  
  41.   -nowarn                    Generate no warnings   
  42. </ERROR>   
  43. Process exitValue=2  
  44.   -verbose                   Output messages about what the compiler is doing   
  45. </ERROR>   
  46. Process exitValue=2  
  47.   -deprecation               Output source locations where deprecated APIs are used   
  48. </ERROR>   
  49. Process exitValue=2  
  50.   -classpath <path>          Specify where to find user class files and annotation processors   
  51. </ERROR>   
  52. Process exitValue=2  
  53.   -cp <path>                 Specify where to find user class files and annotation processors   
  54. </ERROR>   
  55. Process exitValue=2  
  56.   -sourcepath <path>         Specify where to find input source files   
  57. </ERROR>   
  58. Process exitValue=2  
  59.   -bootclasspath <path>      Override location of bootstrap class files   
  60. </ERROR>   
  61. Process exitValue=2  
  62.   -extdirs <dirs>            Override location of installed extensions   
  63. </ERROR>   
  64. Process exitValue=2  
  65.   -endorseddirs <dirs>       Override location of endorsed standards path   
  66. </ERROR>   
  67. Process exitValue=2  
  68.   -proc:{none,only}          Control whether annotation processing and/or compilation is done.   
  69. </ERROR>   
  70. Process exitValue=2  
  71.   -processor <class1>[,<class2>,<class3>...]Names of the annotation processors to run; bypasses default discovery process   
  72. </ERROR>   
  73. Process exitValue=2  
  74.   -processorpath <path>      Specify where to find annotation processors   
  75. </ERROR>   
  76. Process exitValue=2  
  77.   -d <directory>             Specify where to place generated class files   
  78. </ERROR>   
  79. Process exitValue=2  
  80.   -s <directory>             Specify where to place generated source files   
  81. </ERROR>   
  82. Process exitValue=2  
  83.   -implicit:{none,class}     Specify whether or not to generate class files for implicitly referenced files    
  84. </ERROR>   
  85. Process exitValue=2  
  86.   -encoding <encoding>       Specify character encoding used by source files   
  87. </ERROR>   
  88. Process exitValue=2  
  89.   -source <release>          Provide source compatibility with specified release   
  90. </ERROR>   
  91. Process exitValue=2  
  92.   -target <release>          Generate class files for specific VM version   
  93. </ERROR>   
  94. Process exitValue=2  
  95.   -version                   Version information   
  96. </ERROR>   
  97. Process exitValue=2  
  98.   -help                      Print a synopsis of standard options   
  99. </ERROR>   
  100. Process exitValue=2  
  101.   -Akey[=value]              Options to pass to annotation processors   
  102. </ERROR>   
  103. Process exitValue=2  
  104.   -X                         Print a synopsis of nonstandard options   
  105. </ERROR>   
  106. Process exitValue=2  
  107.   -J<flag>                   Pass <flag> directly to the runtime system   
  108. </ERROR>   
  109. Process exitValue=2  
  110. </ERROR>   
  111. Process exitValue=2  

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

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

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

大家注意下

猜你喜欢

转载自wsqwsq000.iteye.com/blog/1120594
今日推荐