Java调用本地命令

Posted ontway

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java调用本地命令相关的知识,希望对你有一定的参考价值。

参考:http://blog.csdn.net/zhu_xun/article/details/19539513

          http://www.cnblogs.com/kingcucumber/p/3180146.html

一、Process类

ProcessBuilder.start()创建一个本机进程,并返回一个Process子类的一个实例,该实例可以获取进程的相关信息,也可以控制进程。这个进程没有自己的终端,它的操作结果io都重定向到了它的父进程,父进程通过getInputStream(),getOutputStream(),getErrorStream()为子进程提供输入和获取输出,而对于io流如果有缓冲大小限制,则可能出现阻塞,导致死锁情况。

可使用destory()方式强制杀掉子进程,exitValue()返回执行结果,如果子进程需要等待返回,调用waitFor()方法将当前线程等待,直到子进程退出。

二、Runtime类

Runtime.getRuntime().exec() 获得的就是Process类,exec()方法有多个重载可以使用,针对不同的情况设置不同的参数。另外需要注意的是执行的windows和linux的明林的写法是不同的。

  

public static void main(String[] args) {
                String command = "notepad.exe txt.txt";

               try {
                Process process = Runtime.getRuntime().exec(command);
                BufferedInputStream bis = new BufferedInputStream(
                        process.getInputStream());
                BufferedReader br = new BufferedReader(new InputStreamReader(bis));
                String line;
                while ((line = br.readLine()) != null) {
                    System.out.println(line);
                }

                process.waitFor();
                if (process.exitValue() != 0) {
                    System.out.println("error!");
                }

                bis.close();
                br.close();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

        }

三、Apache Common-Exec 

强烈建议使用apache的第三方库,该库提供了更加详细的设置和监控方法等等。

执行的命令被称为CommandLine,可使用该类的addArgument()方法为其添加参数,parse()方法将你提供的命令包装好一个可执行的命令。命令是由执行器Executor类来执行的,DefaultExecutor类的execute()方法执行命令,exitValue也可以通过该方法返回接收。设置ExecuteWatchdog可指定进程在出错后多长时间结束,这样有效防止了run-away的进程。此外common-exec还支持异步执行,Executor通过设置一个ExecuteResultHandler类,该类的实例会接收住错误异常和退出代码。

CommandLine cmdLine = new CommandLine("AcroRd32.exe");
cmdLine.addArgument("/p");
    cmdLine.addArgument("/h");
    cmdLine.addArgument("${file}");
    HashMap map = new HashMap();
    map.put("file", new File("invoice.pdf"));
    commandLine.setSubstitutionMap(map);

    DefaultExecuteResultHandler resultHandler = new DefaultExecuteResultHandler();

    ExecuteWatchdog watchdog = new ExecuteWatchdog(60*1000);
    Executor executor = new DefaultExecutor();
    executor.setExitValue(1);
    executor.setWatchdog(watchdog);
    executor.execute(cmdLine, resultHandler);

    // some time later the result handler callback was invoked so we
    // can safely request the exit value
    int exitValue = resultHandler.waitFor();

 

 

一、Java中关于ProcessBuilder 和 Runtime 类的介绍

在Java中要想执行脚本或者调用程序必须通过ProcessBuilder 和 Runtime 类,以上两个类任选一个就行,关于他们的介绍如下:

ProcessBuilder.start() 和 Runtime.exec() 方法都被用来创建一个操作系统进程(执行命令行操作),并返回 Process 子类的一个实例,该实例可用来控制进程状态并获得相关信息。
Process 类提供了执行从进程输入、执行输出到进程、等待进程完成、检查进程的退出状态以及销毁(杀掉)进程的方法。创建进程的方法可能无法针对某些本机平台上的特定进程很好地工作,比如,本机窗口进程,守护进程,Microsoft Windows 上的 Win16/DOS 进程,或者 shell 脚本。创建的子进程没有自己的终端或控制台。它的所有标准 io(即 stdin、stdout 和 stderr)操作都将通过三个流 (getOutputStream()、getInputStream() 和 getErrorStream()) 重定向到父进程。父进程使用这些流来提供到子进程的输入和获得从子进程的输出。因为有些本机平台仅针对标准输入和输出流提供有限的缓冲区大小,如果读写子 进程的输出流或输入流迅速出现失败,则可能导致子进程阻塞,甚至产生死锁。 当没有 Process 对象的更多引用时,不是删掉子进程,而是继续异步执行子进程。 对于带有 Process 对象的 Java 进程,没有必要异步或并发执行由 Process 对象表示的进程。
每个ProcessBuilder实例管理一个进程属性集。ProcessBuilder的start()方法利用这些属性创建一个新的Process实例。start()方法可以从同一实例重复调用,以利用相同或者相关的属性创建新的子进程。
不同点:
ProcessBuilder.start() 和 Runtime.exec()传递的参数有所不同,Runtime.exec()可接受一个单独的字符串,这个字符串是通过空格来分隔可执行命令程序和参数的;也可以接受字符串数组参数。而ProcessBuilder的构造函数是一个字符串列表或者数组。列表中第一个参数是可执行命令程序,其他的是命令行执行是需要的参数。
通过查看JDK源码可知,Runtime.exec最终是通过调用ProcessBuilder来真正执行操作的。

二、Runtime演示示例

1.在windows下调用dos命令:

下面演示了在windows下执行dos命令"chdir",并将执行结果输出的示例。

public class TestDos {  
  
    /** 
     * 在windows下执行dos命令并在console端输出 
     *  
     * @throws Exception  
     */  
    public static void main(String[] args) throws Exception {  
        String strCmd = "chdir";//待执行的dos命令(chdir命令作用是列出当前的工作目录)  
        Process process = Runtime.getRuntime().exec("cmd /k " + strCmd);//通过cmd程序执行cmd命令  
        //process.waitFor();  
        //读取屏幕输出  
        BufferedReader strCon = new BufferedReader(new InputStreamReader(process.getInputStream()));  
        String line;  
        while ((line = strCon.readLine()) != null) {  
            System.out.println(line);  
            }  
    }  
}  

如果不需要进行屏幕输出的话可以简写成如下方式:

public class TestDos {  
  
    /** 
     * 在windows下调用dos命令 
     *  
     * @throws Exception  
     */  
    public static void main(String[] args) throws Exception {  
        String strCmd = "dos命令";//待执行的dos命令  
        Runtime.getRuntime().exec("cmd /c " + strCmd).waitFor();//通过cmd程序执行dos命令  
    }  
}  

注:执行dos命令时,需在命令前加上"cmd /x"参数,其中x可以为c或者k值,具体说明如下:

 

cmd /c chdir 是执行完dir命令后关闭命令窗口。
cmd /k chdir 是执行完dir命令后不关闭命令窗口。
cmd /c start chdir 会打开一个新窗口后执行dir指令,原窗口会关闭。
cmd /k start chdir 会打开一个新窗口后执行dir指令,原窗口不会关闭。

2.在windows下调用外部程序:

下面演示了调用QQ程序的过程:

/** 
 * 在windows下调用QQ程序示例 
 * */  
public class CallQQ {  
  
    /** 
     * @param args 
     * @throws Exception  
     */  
    public static void main(String[] args) throws Exception {  
        Runtime.getRuntime().exec("D:\\\\Program Files (x86)\\\\Tencent\\\\QQ\\\\QQProtect\\\\Bin\\\\QQProtect.exe");  
    }  
}  

3.在Linux下执行shell命令:

 

下面演示了在Linux中执行shell命令pwd,并显示执行结果:

/** 
 * 执行Linux的shell命令并在console端输出结果 
 * */  
public class CallShell {  
  
    /** 
     * @throws Exception  
     */  
    public static void main(String[] args) throws Exception {  
        String strCmd = "pwd";//执行shell命令  
        Process process = Runtime.getRuntime().exec(strCmd);//通过执行cmd命令调用protoc.exe程序  
        BufferedReader strCon = new BufferedReader(new InputStreamReader(process.getInputStream()));  
        String line;  
        while ((line = strCon.readLine()) != null) {  
            System.out.println("java print:"+line);  
            }  
    }  
}  

4.在Linux下调用shell脚本并输出结果:

/** 
 * 在linux下调用shell脚本并在console端输出脚本的执行结果 
 * */  
public class CallShell {  
  
    /** 
     * @throws Exception  
     */  
    public static void main(String[] args) throws Exception {  
        String strCmd = "/home/zhu/test/test.sh";//待调用shell脚本  
        Process process = Runtime.getRuntime().exec(strCmd);//通过执行cmd命令调用protoc.exe程序  
        BufferedReader strCon = new BufferedReader(new InputStreamReader(process.getInputStream()));  
        String line;  
        while ((line = strCon.readLine()) != null) {  
            System.out.println("java print:"+line);  
            }  
    }  
}  

三、ProcessBuilder使用示例

 

ProcessBuilder的使用参考如下:

String[] as = new String[]{“待执行命令1”,"待执行命令2",.........};
ProcessBuilder pb = new ProcessBuilder(as);
pb.start();
使用ProcessBuilder可以依次执行多个命令

以上是关于Java调用本地命令的主要内容,如果未能解决你的问题,请参考以下文章

01_JNI是什么,为什么使用,怎么用JNI,Cygwin环境变量配置,NDK案例(使用Java调用C代码),javah命令使用

Java调用本地命令

Oracle 数据库 - 使用UEStudio修改dmp文件版本号,解决imp命令恢复的数据库与dmp本地文件版本号不匹配导致的导入失败问题,“ORACLE error 12547”问题处理(代码片段

wsimport命令生成webService java客户端代码

java.lang.IllegalStateException:片段未附加到活动

导航到另一个片段时触发 API 调用