2010-09-20 30 views
10

我寫了下面的java代碼,它執行另一個名爲「Newsworthy_RB」的Java程序。如何使java程序同時打印out.println()和err.println()語句?

Newsworthy_RB.java包含System.out.printlln()和System.err.println()語句。

我想要在命令提示符控制檯中打印輸出。

需要做什麼才能獲得相同的結果。

下面的程序只是打印out.println()語句而不是err.println()語句。

請讓我知道下面的代碼是否會像我期望的那樣工作?

command = "java -cp .:../sqljdbc.jar SetHash Newsworthy_RB"; 
Process child1 = Runtime.getRuntime().exec(command); 
InputStream in1 = child1.getErrorStream(); 
InputStream in2 = child2.getInputStream(); 
while ((c = in1.read()) != -1 || (c = in2.read()) != -1) { 
     System.out.print((char)c); 
    } 

回答

14

首先,啓動外部程序的首選方式是通過ProcessBuilder。它甚至在the docs for Runtime提到:

ProcessBuilder.start()是從現在開始的處理與修改後的環境的首選方式。

ProcessBuilder你有一個非常方便的方法叫redirectErrorStream

設置此進程生成器的redirectErrorStream屬性。

如果該屬性爲真,則通過隨後通過該對象的開始啓動的子進程產生的任何錯誤輸出()方法將與標準輸出合併,這樣既可以通過Process.getInputStream(讀取) 方法。這樣可以更容易地將錯誤消息與相應的輸出相關聯。初始值爲false。

的一個完整的例子如何同時輸出標準錯誤和標準輸出:

import java.io.*; 

public class Test { 
    public static void main(String... args) throws IOException { 

     ProcessBuilder pb = 
       new ProcessBuilder("java", "-cp", "yourClassPath", "HelloWorld"); 

     pb.redirectErrorStream(true); 
     Process proc = pb.start(); 

     Reader reader = new InputStreamReader(proc.getInputStream()); 
     int ch; 
     while ((ch = reader.read()) != -1) 
      System.out.print((char) ch); 
     reader.close(); 
    } 
} 

回答您的更新:否,代碼與

while ((c = in1.read()) != -1 || (c = in2.read()) != -1) 

不會工作,因爲read()是一個阻塞方法,你只有一個線程。您唯一的選擇是對每個輸入流使用一個線程,或(最好)將兩個輸入流合併爲一個,使用ProcessBuilder.redirectErrorStream

+0

我只是喜歡這種解釋。非常感謝您的回覆。但暫時,請讓我知道我在我的問題中所做的修改是否會起作用? – LGAP 2010-09-20 20:01:15

+0

我在將來的程序中肯定會實現ProcessBuilder概念。 – LGAP 2010-09-20 20:01:35

+0

也讓我知道'ProcessBuilder pb = new ProcessBuilder(「java」,「HelloWorld」);'如何在此聲明中提及程序的類路徑? – LGAP 2010-09-20 20:04:45

10

您需要在單獨的線程中管道輸出兩個流。從實施例here代碼:

Process p = Runtime.getRuntime().exec(cmd.array()); 
copyInThread(p.getInputStream(), System.out); 
copyInThread(p.getErrorStream(), System.err); 
p.waitFor(); 
return p.exitValue(); 

private void copyInThread(final InputStream in, final OutputStream out) { 
    new Thread() { 
     public void run() { 
      try { 
       while (true) { 
        int x = in.read(); 
        if (x < 0) { 
         return; 
        } 
        if (out != null) { 
         out.write(x); 
        } 
       } 
      } catch (Exception e) { 
       throw new RuntimeException(e); 
      } 
     } 
    } .start(); 
} 
+0

感謝您的回覆穆勒。我更新了我的問題。請讓我知道那工作與否? – LGAP 2010-09-20 19:58:13

+3

從'Runtime'的文檔:「ProcessBuilder.start()現在是使用修改後的環境啓動進程的首選方式。」我建議使用'ProcessBuilder.redirectErrorStream'。 (查看我的回答。) – aioobe 2010-09-20 20:00:09

+0

@aioobe:你是對的!我不知道ProcessBuilder。 – 2010-09-20 20:22:19

1

有在過程對象兩種方法:getErrorStream和的getInputStream。目前,你的程序只能聽一個。你會希望它聽兩者。