java调用其他程序的问题

java调用其他程序的问题

 

大家都知道java调用cmd 用的是Runtimeexec()方法。该方法最终重启一个进程去执行命令,因为该方法最终调用了
ProcessBuilder:

1   public  Process exec(String[] strings, String[] strings_2_, File file)
2      throws  IOException  {
3    return new ProcessBuilder(strings).environment(strings_2_).directory
4           (file).start();
5    }
既然是重启了一个进程,那么就存在异步的问题,但是在很多情况在更想同步的调用Runtimeexec(),那么怎么办呢?
Runtime.exec()
的返回值Process提供了waitFor()方法,可以达到阻塞新进程的目的。但是只调用waitFor(),该字线程就会
一直阻塞,所以只调用waitFor()还是不够的,我们需要以读取他的输出流的方式来阻塞住线程,当输出流读取结束的
时候让阻塞结束,代码如下:

BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
        String str 
= "";
        
        
while ((str = bufferedReader.readLine()) != null{
            System.out.println(str);
        }

    process.waitFor(); 
   通过读取输出流和调用process.waitFor()可以的实现调用Runtime.exec()的同步。
  
另外还有一种情况可以使Runtime.exec()出现阻塞,Runtimeexec()在执行时会产生两种输出流:错误输出流和标准输出流,当进程结束时会关闭这两个流,在上面的代码里只读取了标准输出流而没有导致错误输出流,由于错误输出流中的数据没有被读取,进程就不会结束,因此调用readLine()方法时整个程序就会阻塞,因此,我们不仅要读取标准输出流还要读取错误输出流,由于读取这些流都会阻塞,所以想同时读取两个流还不是那么容易,一种办法就是启动线程分别读取不同的输出流,另外一个办法就是使用ProcessBuilder来执行(前面已经说过了Runtime.exec()最终也是调用ProcessBuilder来执行的),因为ProcessBuilder有一个redirectErrorStream(),方法设置为redirectErrorStream(true),就可以使错误输出流合并到标准输出流,这样我们就只需要读取标准输出流就可以完全解决问题了,代码如下:

 1private static void execCmd(Properties properties) throws Exception {
 2
 3
 4        File file = new File("执行命令的目录");
 5
 6        ListString> cmdList = new ArrayListString>();
 7        cmdList.add("cmd.exe");
 8        cmdList.add("/c");
 9        cmdList.add(CMD);//CMD是执行的命令
10        
11        ProcessBuilder pb = new ProcessBuilder(cmdList);
12        pb.directory(file);
13        pb.redirectErrorStream(true);//将错误输出流合并到标准输出流
14        Process process = pb.start();
15        
16        print(process);
17    }

18
19    
20    public static void print(Process process) throws Exception {
21        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
22        String str = "";
23            
24        while ((str = bufferedReader.readLine()) != null{
25            System.out.println(str);
26        }

27        
28        cs.close();
29        process.waitFor(); 
30    }
还是也介绍下使用线程来分别读取错误输出流和标准输出流吧:

 1import java.util.*;
 2import java.io.*;
 3
 4class StreamWatch extends Thread {
 5InputStream is;
 6
 7String type;
 8
 9ListString> output = new ArrayListString>();
10
11boolean debug = false;
12
13StreamWatch(InputStream is, String type) {
14   this(is, type, false);
15}

16
17StreamWatch(InputStream is, String type, boolean debug) {
18   this.is = is;
19   this.type = type;
20   this.debug = debug;
21}

22
23public void run() {
24   try {
25    PrintWriter pw = null;
26
27    InputStreamReader isr = new InputStreamReader(is);
28    BufferedReader br = new BufferedReader(isr);
29    String line = null;
30    while ((line = br.readLine()) != null{
31     output.add(line);
32     if (debug)
33      System.out.println(type + ">" + line);
34    }

35    if (pw != null)
36     pw.flush();
37   }
 catch (IOException ioe) {
38    ioe.printStackTrace();
39   }

40}

41
42public ListString> getOutput() {
43   return output;
44}

45}

46
47public class Test5 {
48public static void main(String args[]) {
49   try {
50    ListString> list = new ArrayListString>();
51    ProcessBuilder pb = null;
52    Process p = null;
53
54    // list the files and directorys under C:\
55    list.add("CMD.EXE");
56    list.add("/C");
57    list.add("dir1");
58    pb = new ProcessBuilder(list);
59    pb.directory(new File("C:\\"));
60    p = pb.start();
61
62    // process error and output message
63    StreamWatch errorWatch = new StreamWatch(p.getErrorStream(),
64      "ERROR");
65    StreamWatch outputWatch = new StreamWatch(p.getInputStream(),
66      "OUTPUT");
67
68    // start to watch
69    errorWatch.start();
70    outputWatch.start();
71
72    //wait for exit
73    int exitVal = p.waitFor();
74
75    //print the content from ERROR and OUTPUT
76    System.out.println("ERROR: " + errorWatch.getOutput());
77    System.out.println("OUTPUT: " + outputWatch.getOutput());
78   
79    System.out.println("the return code is " + exitVal);
80
81   }
 catch (Throwable t) {
82    t.printStackTrace();
83   }

84}

85}

86
87
88
 

好了,今天就先写到这里吧。



你可能感兴趣的:(java调用其他程序的问题)