成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

如何在Java中執行其它程序

開發 后端
以下講述在編寫Java程序時,如何在Java中執行其它程序,如啟動程序等。

在編寫Java程序時,有時候需要在Java程序中執行另外一個程序。

1、啟動程序
Java提供了兩種方法用來啟動其它程序:

(1)使用Runtime的exec()方法

(2)使用ProcessBuilder的start()方法

不管在哪種操作系統下,程序具有基本類似的一些屬性。一個程序啟動后就程序操作系統的一個進程,進程在執行的時候有自己的環境變量、有自己的工作目錄。Runtime和ProcessBuilder提供了不同的方式來啟動程序,設置啟動參數、環境變量和工作目錄。

能夠在Java中執行的外部程序,必須是一個實際存在的可執行文件,對于shell下的內嵌命令是不能直接執行的。
采用Runtime的exec執行程序時,首先要使用Runtime的靜態方法得到一個Runtime,然后調用Runtime的exec方法。可以將要執行的外部程序和啟動參數、環境變量、工作目錄作為參數傳遞給exec方法,該方法執行后返回一個Process代表所執行的程序。

Runtime有六個exec方法,其中兩個的定義為:

public Process exec(String[] cmdarray, String[] envp, File dir)

public Process exec(String command, String[] envp, File dir)

cmdarray和command為要執行的命令,可以將命令和參數作為一個字符串command傳遞給exec()方法,也可以將命令和參數一個一個的方在數組cmdarray里傳遞給exec()方法。

envp為環境變量,以name=value的形式放在數組中。dir為工作目錄。

可以不要dir參數,或者不要envp和dir參數,這樣就多出了其它4個exec()方法。如果沒有dir參數或者為null,那么新啟動的進程就繼承當前java進程的工作目錄。如果沒有envp參數或者為null,那么新啟動的進程就繼承當前java進程的環境變量。

也可以使用ProcessBuilder類啟動一個新的程序,該類是后來添加到JDK中的,而且被推薦使用。通過構造函數設置要執行的命令以及參數,或者也可以通過command()方法獲取命令信息后在進行設置。通過directory(File directory) 方法設置工作目錄,通過environment()獲取環境變量信息來修改環境變量。

在使用ProcessBuilder構造函數創建一個新實例,設置環境變量、工作目錄后,可以通過start()方法來啟動新程序,與Runtime的exec()方法一樣,該方法返回一個Process對象代表啟動的程序。

ProcessBuilder與Runtime.exec()方法的不同在于ProcessBuilder提供了redirectErrorStream(boolean redirectErrorStream) 方法,該方法用來將進程的錯誤輸出重定向到標準輸出里。即可以將錯誤輸出都將與標準輸出合并。

2、Process

不管通過那種方法啟動進程后,都會返回一個Process類的實例代表啟動的進程,該實例可用來控制進程并獲得相關信息。Process 類提供了執行從進程輸入、執行輸出到進程、等待進程完成、檢查進程的退出狀態以及銷毀(殺掉)進程的方法:

(1) void destroy()
殺掉子進程。
一般情況下,該方法并不能殺掉已經啟動的進程,不用為好。

(2) int exitValue()
返回子進程的出口值。
只有啟動的進程執行完成、或者由于異常退出后,exitValue()方法才會有正常的返回值,否則拋出異常。

(3)InputStream getErrorStream()
獲取子進程的錯誤流。
如果錯誤輸出被重定向,則不能從該流中讀取錯誤輸出。

(4)InputStream getInputStream()
獲取子進程的輸入流。
可以從該流中讀取進程的標準輸出。

(5)OutputStream getOutputStream()
獲取子進程的輸出流。
寫入到該流中的數據作為進程的標準輸入。

(6) int waitFor()
導致當前線程等待,如有必要,一直要等到由該 Process 對象表示的進程已經終止。
        
通過該類提供的方法,可以實現與啟動的進程之間通信,達到交互的目的。

3、從標準輸出和錯誤輸出流讀取信息

從啟動其他程序的Java進程看,已啟動的其他程序輸出就是一個普通的輸入流,可以通過getInputStream()和getErrorStream來獲取。

對于一般輸出文本的進程來說,可以將InputStream封裝成BufferedReader,然后就可以一行一行的對進程的標準輸出進行處理。

4、舉例

(1)Runtime.exec()

import java.io.BufferedReader;
import java.io.File;
import java.io.InputStreamReader;

public class Test1 {
public static void main(String[] args) {
   try {
    Process p = null;
    String line = null;
    BufferedReader stdout = null;

    //list the files and directorys under C:\
    p = Runtime.getRuntime().exec("CMD.exe /C dir", null, new File("C:\\"));
    stdout = new BufferedReader(new InputStreamReader(p
      .getInputStream()));
    while ((line = stdout.readLine()) != null) {
     System.out.println(line);
    }
    stdout.close();

    //echo the value of NAME
    p = Runtime.getRuntime().exec("CMD.exe /C echo %NAME%", new String[] {"NAME=TEST"});  
    stdout = new BufferedReader(new InputStreamReader(p
      .getInputStream()));
    while ((line = stdout.readLine()) != null) {
     System.out.println(line);
    }
    stdout.close();
   } catch (Exception e) {
    e.printStackTrace();
   }
}

}


(2)ProcessBuilder

import java.io.BufferedReader;
import java.io.File;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

public class Test2 {
public static void main(String[] args) {
   try {
    List list = new ArrayList();
    ProcessBuilder pb = null;
    Process p = null;
    String line = null;
    BufferedReader stdout = null;
  
    //list the files and directorys under C:\
    list.add("CMD.EXE");
    list.add("/C");
    list.add("dir");
    pb = new ProcessBuilder(list);
    pb.directory(new File("C:\\"));
    p = pb.start();
  
    stdout = new BufferedReader(new InputStreamReader(p
      .getInputStream()));
    while ((line = stdout.readLine()) != null) {
     System.out.println(line);
    }
    stdout.close();

    //echo the value of NAME
    pb = new ProcessBuilder();
    pb.command(new String[] {"CMD.exe", "/C", "echo %NAME%"});
    pb.environment().put("NAME", "TEST");
    p = pb.start();
  
    stdout = new BufferedReader(new InputStreamReader(p
      .getInputStream()));
    while ((line = stdout.readLine()) != null) {
     System.out.println(line);
    }
    stdout.close();
   } catch (Exception e) {
    e.printStackTrace();
   }
}

}


5、獲取進程的返回值

通常,一個程序/進程在執行結束后會向操作系統返回一個整數值,0一般代表執行成功,非0表示執行出現問題。有兩種方式可以用來獲取進程的返回值。一是利用waitFor(),該方法是阻塞的,執導進程執行完成后再返回。該方法返回一個代表進程返回值的整數值。另一個方法是調用exitValue()方法,該方法是非阻塞的,調用立即返回。但是如果進程沒有執行完成,則拋出異常。

6、阻塞的問題

由Process代表的進程在某些平臺上有時候并不能很好的工作,特別是在對代表進程的標準輸入流、輸出流和錯誤輸出進行操作時,如果使用不慎,有可能導致進程阻塞,甚至死鎖。

如果將以上事例中的從標準輸出重讀取信息的語句修改為從錯誤輸出流中讀取:

stdout = new BufferedReader(new InputStreamReader(p
.getErrorStream()));

那么程序將發生阻塞,不能執行完成,而是hang在那里。

當進程啟動后,就會打開標準輸出流和錯誤輸出流準備輸出,當進程結束時,就會關閉他們。在以上例子中,錯誤輸出流沒有數據要輸出,標準輸出流中有數據輸出。由于標準輸出流中的數據沒有被讀取,進程就不會結束,錯誤輸出流也就不會被關閉,因此在調用readLine()方法時,整個程序就會被阻塞。為了解決這個問題,可以根據輸出的實際先后,先讀取標準輸出流,然后讀取錯誤輸出流。

但是,很多時候不能很明確的知道輸出的先后,特別是要操作標準輸入的時候,情況就會更為復雜。這時候可以采用線程來對標準輸出、錯誤輸出和標準輸入進行分別處理,根據他們之間在業務邏輯上的關系決定讀取那個流或者寫入數據。

針對標準輸出流和錯誤輸出流所造成的問題,可以使用ProcessBuilder的redirectErrorStream()方法將他們合二為一,這時候只要讀取標準輸出的數據就可以了。

當在程序中使用Process的waitFor()方法時,特別是在讀取之前調用waitFor()方法時,也有可能造成阻塞。可以用線程的方法來解決這個問題,也可以在讀取數據后,調用waitFor()方法等待程序結束。

總之,解決阻塞的方法應該有兩種:

(1)使用ProcessBuilder類,利用redirectErrorStream方法將標準輸出流和錯誤輸出流合二為一,在用start()方法啟動進程后,先從標準輸出中讀取數據,然后調用waitFor()方法等待進程結束。

如:

import java.io.BufferedReader;
import java.io.File;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

public class Test3 {
public static void main(String[] args) {
   try {
    List list = new ArrayList();
    ProcessBuilder pb = null;
    Process p = null;
    String line = null;
    BufferedReader stdout = null;
  
    //list the files and directorys under C:\
    list.add("CMD.EXE");
    list.add("/C");
    list.add("dir");
    pb = new ProcessBuilder(list);
    pb.directory(new File("C:\\"));
    //merge the error output with the standard output
    pb.redirectErrorStream(true);
    p = pb.start();
  
    //read the standard output
    stdout = new BufferedReader(new InputStreamReader(p
      .getInputStream()));
    while ((line = stdout.readLine()) != null) {
     System.out.println(line);
    }
    int ret = p.waitFor();
    System.out.println("the return code is " + ret);
  
    stdout.close();

   } catch (Exception e) {
    e.printStackTrace();
   }
}

}


(2)使用線程

import java.util.*;
import java.io.*;

class StreamWatch extends Thread {
InputStream is;

String type;

List output = new ArrayList();

boolean debug = false;

StreamWatch(InputStream is, String type) {
   this(is, type, false);
}

StreamWatch(InputStream is, String type, boolean debug) {
   this.is = is;
   this.type = type;
   this.debug = debug;
}

public void run() {
   try {
    PrintWriter pw = null;

    InputStreamReader isr = new InputStreamReader(is);
    BufferedReader br = new BufferedReader(isr);
    String line = null;
    while ((line = br.readLine()) != null) {
     output.add(line);
     if (debug)
      System.out.println(type + ">" + line);
    }
    if (pw != null)
     pw.flush();
   } catch (IOException ioe) {
    ioe.printStackTrace();
   }
}

public List getOutput() {
   return output;
}
}

public class Test5 {
public static void main(String args[]) {
   try {
    List list = new ArrayList();
    ProcessBuilder pb = null;
    Process p = null;

    // list the files and directorys under C:\
    list.add("CMD.EXE");
    list.add("/C");
    list.add("dir");
    pb = new ProcessBuilder(list);
    pb.directory(new File("C:\\"));
    p = pb.start();

    // process error and output message
    StreamWatch errorWatch = new StreamWatch(p.getErrorStream(),
      "ERROR");
    StreamWatch outputWatch = new StreamWatch(p.getInputStream(),
      "OUTPUT");

    // start to watch
    errorWatch.start();
    outputWatch.start();

    //wait for exit
    int exitVal = p.waitFor();

    //print the content from ERROR and OUTPUT
    System.out.println("ERROR: " + errorWatch.getOutput());
    System.out.println("OUTPUT: " + outputWatch.getOutput());
  
    System.out.println("the return code is " + exitVal);

   } catch (Throwable t) {
    t.printStackTrace();
   }
}
}

7、在Java中執行Java程序

執行一個Java程序的關鍵在于:

(1)知道JAVA虛擬機的位置,即java.exe或者java的路徑

(2)知道要執行的java程序的位置

(3)知道該程序所依賴的其他類的位置

舉一個例子,一目了然。

(1)待執行的Java類

public class MyTest {
public static void main(String[] args) {
   System.out.println("OUTPUT one");
   System.out.println("OUTPUT two");
   System.err.println("ERROR 1");
   System.err.println("ERROR 2"); 
   for(int i = 0; i < args.length; i++)
   {
    System.out.printf("args[%d] = %s.", i, args[i]);
   }
}
}


(2)執行該類的程序


import java.util.*;
import java.io.*;

class StreamWatch extends Thread {
InputStream is;

String type;

List output = new ArrayList();

boolean debug = false;

StreamWatch(InputStream is, String type) {
   this(is, type, false);
}

StreamWatch(InputStream is, String type, boolean debug) {
   this.is = is;
   this.type = type;
   this.debug = debug;
}

public void run() {
   try {
    PrintWriter pw = null;

    InputStreamReader isr = new InputStreamReader(is);
    BufferedReader br = new BufferedReader(isr);
    String line = null;
    while ((line = br.readLine()) != null) {
     output.add(line);
     if (debug)
      System.out.println(type + ">" + line);
    }
    if (pw != null)
     pw.flush();
   } catch (IOException ioe) {
    ioe.printStackTrace();
   }
}

public List getOutput() {
   return output;
}
}

public class Test6 {
public static void main(String args[]) {
   try {
    List list = new ArrayList();
    ProcessBuilder pb = null;
    Process p = null;
  
    String java = System.getProperty("java.home") + File.separator + "bin" + File.separator + "java";
    String classpath = System.getProperty("java.class.path");
    // list the files and directorys under C:\
    list.add(java);
    list.add("-classpath");
    list.add(classpath);
    list.add(MyTest.class.getName());
    list.add("hello");
    list.add("world");
    list.add("good better best");
  
    pb = new ProcessBuilder(list);
    p = pb.start();
  
    System.out.println(pb.command());

    // process error and output message
    StreamWatch errorWatch = new StreamWatch(p.getErrorStream(),
      "ERROR");
    StreamWatch outputWatch = new StreamWatch(p.getInputStream(),
      "OUTPUT");

    // start to watch
    errorWatch.start();
    outputWatch.start();

    //wait for exit
    int exitVal = p.waitFor();

    //print the content from ERROR and OUTPUT
    System.out.println("ERROR: " + errorWatch.getOutput());
    System.out.println("OUTPUT: " + outputWatch.getOutput());
  
    System.out.println("the return code is " + exitVal);

   } catch (Throwable t) {
    t.printStackTrace();
   }
}
}

【編輯推薦】

  1. 我們為什么要學習Java:Java的八大優點
  2. 淺談Java中使用遞歸方法刪除文件
  3. JavaFX和Java之間的互操作性
責任編輯:王觀 來源: Java學習室
相關推薦

2021-09-16 17:38:49

UbuntuLinuxJava

2017-04-13 10:46:14

Webpack執行代碼分割

2023-04-04 07:52:26

RedisLua腳本

2024-05-31 12:54:37

.NET CoreLinux語言

2016-07-29 11:21:16

Ubuntulinux程序

2011-09-07 13:23:56

Ubuntu

2023-09-27 23:24:50

C++鏈表

2021-06-01 21:22:44

解析域名編程

2009-07-10 17:54:15

Java中調用JythJython

2018-10-29 10:13:29

Windows 10應用程序卸載

2016-12-20 09:30:22

shell腳本linux

2019-10-30 09:00:00

Windows 10Windows Def離線掃描

2019-03-27 13:20:31

Windows 10更新驅動程序

2011-05-17 09:32:25

DB2

2022-04-01 07:35:45

IDEAJavaWeb 項目

2011-05-18 10:42:48

2009-06-17 13:19:50

Java調用DLL

2018-06-05 08:51:04

Linux結束進程中止程序

2021-09-14 12:34:33

LinuxLinux終端

2016-10-12 08:38:24

Windows 10Defender命令行
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 国产一级一片免费播放 | 亚洲国产精品一区二区久久 | 天天综合网91 | 欧美国产一区二区 | 亚洲精品国产综合区久久久久久久 | 欧美日韩专区 | 欧美日韩亚洲系列 | 久久久久久中文字幕 | 日韩一级免费电影 | 亚洲成人福利在线观看 | 可以在线观看av的网站 | 久久成人精品视频 | 黄色av观看| www.久草.com | 日韩快播电影网 | 久草资源在线 | 国产一区久久 | 91久久爽久久爽爽久久片 | 欧美精品1区2区3区 精品国产欧美一区二区 | 亚洲福利| 超碰97人人人人人蜜桃 | 久久久久久国产一区二区三区 | 精品九九久久 | 中文在线一区 | 黄网站在线观看 | 亚洲精品乱码久久久久久蜜桃91 | 久久人爽 | 国产精品视频网站 | 亚洲精品久久 | 99久热在线精品视频观看 | 日韩一二区| 成人影视网址 | 国产精品福利在线 | 天色综合网 | 国产在线一区二区三区 | 日韩伦理一区二区 | 日本中文字幕视频 | 黄色一级免费 | 紧缚调教一区二区三区视频 | 国产探花在线精品一区二区 | 91免费观看国产 |