`
geshenyi
  • 浏览: 100925 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

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

    博客分类:
  • J2SE
阅读更多
经过上一篇的学习,应该对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)


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

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

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

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

改为如下:
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才可以执行。可以是环境上的不同。虽然是输出了结果,但是因为异常中断才输出的结果。也不是我想要的结果。这个又是为什么呢?

以下又是引用别人的话:

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


文档引述完了,作者又开始批评了,他说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里面得到的结果有点不一样。

大家注意下。
分享到:
评论

相关推荐

    Java调用Linux命令

    ### Java调用Linux命令 Java提供了一种强大的机制来执行操作系统级别的任务,其中包括调用Linux命令。实现这一功能的核心是`Runtime`类中的`exec()`方法。这个方法允许Java应用程序创建一个新的进程来执行指定的...

    Java调用应用程序和Dos中的命令

    在Java编程中,有时候我们需要执行一些操作系统级别的任务,例如启动一个外部程序、执行一些系统命令等。这通常可以通过Java的`Runtime`类实现,尤其是通过`Runtime.exec()`方法来创建一个新的进程。本文将详细介绍...

    perl脚本调用练习和调用系统命令并展示输出信息

    标题 "perl脚本调用练习和调用系统命令并展示输出信息" 提示我们这篇内容主要涉及使用Perl脚本执行系统命令以及如何处理输出信息。Perl是一种强大的文本处理语言,常用于系统管理任务,包括调用其他系统工具或程序。...

    windows下java调用ffmpeg视频处理环境搭建

    Java提供了`Runtime.getRuntime().exec()`方法或`ProcessBuilder`类来执行系统命令。例如,我们可以使用以下Java代码来执行一个简单的FFmpeg命令: ```java String command = "ffmpeg -i input.mp4 output.mp4"; ...

    Java调用SPSS的实例

    Java调用SPSS的实例是将Java编程语言与统计分析软件SPSS(Statistical Product and Service Solutions)结合使用的典型应用。SPSS提供了Java接口,使得开发者可以利用Java代码执行SPSS的数据处理和分析任务,无需...

    exchange/powershell,Java调用powershell开通邮箱

    标题 "exchange/powershell,Java调用powershell开通邮箱" 暗示了这是一个关于使用Java编程语言调用PowerShell脚本在Exchange服务器上创建邮箱的教程或项目。Exchange是微软提供的一款企业级电子邮件服务器软件,而...

    java调用R语言源码

    3. **Rscript**: Java可以通过`Runtime.getRuntime().exec()`方法执行系统命令,调用R脚本并捕获输出。这种方法简单,但不适合复杂的交互式任务,因为每次调用都会启动新的R进程。 4. **rJava**: rJava是R的一个...

    java调用视频转换工具ffmpeg.zip

    在Java中调用FFmpeg,通常有两种方式:直接执行系统命令和使用Java库。直接执行命令是通过Runtime.exec()方法或ProcessBuilder类来调用FFmpeg的命令行工具,例如: ```java String command = "ffmpeg -i input.mp4 ...

    java调用spss实例

    Java调用SPSS实例主要涉及的是如何通过编程方式与SPSS进行交互,这在数据分析、自动化报告或构建数据处理系统时非常有用。SPSS(Statistical Product and Service Solutions)是一款强大的统计分析软件,而它的Java...

    java调用本地浏览器的demo

    Java调用本地浏览器的示例,通常涉及到Java与操作系统交互的能力,这主要通过Java的`Runtime`类或者`ProcessBuilder`类实现。这两个类允许Java程序执行系统命令,例如打开一个本地已安装的浏览器来加载特定的URL。...

    java中调用本地exe文件

    通过本文的学习,我们了解到了如何在Java中调用本地exe文件的基本原理、常见应用场景以及具体的代码实现细节。掌握这些技能对于开发人员来说是非常有用的,可以帮助我们更好地利用Java与操作系统之间的交互能力。

    非常好用java调用c++ dll文件demo

    Java调用C++ DLL文件是跨语言编程中的一个重要应用场景,特别是在既有Java代码库又有C++动态链接库的情况下。本文将详细讲解如何在Java程序中调用C++编写的DLL文件,以及一个可用的示例。 首先,理解Java与C++交互...

    java调用python脚本

    例如,"Java调用Python脚本"是一个常见的需求,特别是在数据处理、科学计算或机器学习等场景中,Python的强大库可以与Java的稳定性和企业级应用能力相结合。本教程将详细讲解如何在Java程序中调用Python脚本。 首先...

    java调用shell脚本

    在Java编程中,有时我们需要与操作系统进行交互,执行一些系统级别的任务,比如调用Shell脚本。这在处理自动化任务、远程服务器管理或系统集成时非常常见。在给定的资源中,我们可以看到如何在Java中实现这个功能,...

    用java调用python

    这是原生 Java 提供的方法,通过执行系统命令来运行 Python 脚本。例如,你可以创建一个 `ProcessBuilder` 实例,指定 Python 解释器和脚本路径,然后启动进程。这种方法简单,但效率较低,且不适用于复杂的交互式...

    MAC下java调用opencv包含opencv_454.jar和libopencv_java454.dylib

    在Mac环境下,使用Java调用OpenCV库是一个常见的需求,特别是在计算机视觉和图像处理的项目中。OpenCV是一个强大的开源库,提供了丰富的功能,用于图像处理、计算机视觉算法以及机器学习。本文将详细介绍如何在Mac上...

    windows下java调用ffmpeg视频处理源码

    6. **环境搭建**:配合"windows下java调用ffmpeg视频处理环境搭建",这部分可能包括如何在Windows系统上安装FFmpeg,设置环境变量,以及如何确保Java程序能正确找到并执行FFmpeg的可执行文件。 7. **错误处理和日志...

    JAVA执行shell命令小工具

    这两个类提供了运行外部进程的能力,从而允许Java程序调用系统命令。 在给定的描述中,虽然没有提供具体的信息,但我们可以推测这篇博文可能是博主Qindongliang分享的一个实用工具,可能包括如何在Java代码中构建和...

    java 调用 mplayer

    Java中的`Runtime.getRuntime().exec()`方法允许我们执行系统命令,这就为我们提供了与Mplayer交互的途径。通过构建命令字符串,我们可以启动Mplayer、传递参数(如文件路径)以及执行播放控制操作。 1. **进程管理...

Global site tag (gtag.js) - Google Analytics