2015-06-16 82 views
-1

我正在圍繞一個簡單的C++程序構建一個java GUI,結果證明我只能執行一次。我希望能夠在每次點擊按鈕時運行它,但事實證明它不會讓我。多次從java代碼執行外部程序

我的研究工作:我做我最好做一個簡化的情況重現這個bug。下面的代碼應該打印出「我正在運行」十次。但是,相反,它會以不同的數量打印出這個字符串,每次運行java代碼。我在這裏做錯了什麼?


Java代碼:

import java.io.InputStream; 
import java.io.IOException; 

public class Main{ 
    public static void main(String[] args){ 
     //Declaration of process builder 
     ProcessBuilder pb = new ProcessBuilder("./a.out"); 

     //Loop that should execute a.out 10 times 
     for (int i = 0; i < 10 ; i++) { 
      Process p = null; 
      String s; 
      try{ 
       //Executing pb (a.out) 
       p = pb.start(); 

       //Catching output of a.out 
       InputStream opt = p.getInputStream(); 
       byte[] buffer = new byte[opt.available()]; 
       opt.read(buffer, 0, opt.available()); 
       s = new String(buffer); 
      }catch(IOException ex){} 

      //Printing the output of a.out 
      System.out.println(s); 
      p.destroy(); 
     } 
    } 
} 

該C++程序代碼:

#include <iostream> 

int main(){ 
    std::cout<<"I'm running"; 
} 

輸出:

I'm running 
I'm running 



I'm running 
+0

我不知道我明白你要做什麼。你想要一個帶有按鈕的Java GUI,當你按下該按鈕時,你可以啓動一個程序?你的GUI代碼在哪裏? –

+0

@VinceEmigh是的。不需要GUI代碼,因爲我知道它的工作原理 - 它在第一次點擊後開始處理,但在下次點擊後它不會。你可以在這裏看到簡化的案例。它應該cout「我正在運行」10次。它沒有。 –

回答

1

您正在運行的進程開始異步工作。有時候,C++程序不夠快,無法打印輸出 - 在初始化或開始寫入過程時,它正在終止它。

一旦完成,您應該閱讀它的輸出。天真的方法是在創建流程後立即添加對Process.waitFor()的調用 - 這適用於您在聲明中描述的情況。

但是,這種方法有一個非常大的問題 - 您正在運行的程序可能會用完輸出緩衝區,它將不得不等待,直到您消耗其輸出,因此永遠不會終止。所以如果你運行的程序比較複雜,那麼你必須編寫邏輯,這樣做會消耗輸出並等待程序完成其工作。這裏是例子:

p = pb.start(); 
InputStream opt = p.getInputStream(); 
ByteArrayOutputStream boas = new ByteArrayOutputStream(); 
byte[] buffer = new byte[2048]; 
int bytesRead; 
while (!p.waitFor(50, TimeUnit.MILLISECONDS)) { 
    while ((bytesRead = opt.read(buffer)) > 0) { 
     boas.write(buffer, 0, bytesRead); 
    } 
} 
// Reading the final part of the output 
while ((bytesRead = opt.read(buffer)) > 0) { 
    boas.write(buffer, 0, bytesRead); 
} 
s = new String(boas.toByteArray()); 
System.out.println(s);