2017-05-05 45 views
2

我遇到了一個奇怪的問題。我多次使用過程構建器來調用程序中的可執行文件,但以前從未遇到過。爲了進行調試,我製作了一個方法,將可執行文件的輸出打印到System.out中。一切正常,我的程序很好地導出了我跑過的所有測試gif。進程將不會運行,除非打印輸出+ Processbuilder

當需要爲1000多個gif正確運行此程序時,我將打印輸出方法註釋掉以提高性能。一旦整個程序運行,我回來發現exportGif沒有工作。該程序運行沒有錯誤,但該過程的調用根本沒有按預期輸出gif。

在打印輸出方法中隔離行後,似乎代碼的決定位是reader.readLine()。爲什麼會這樣呢?可執行文件應該已經運行了,調試方法應該只在事實之後讀取輸出流,正確嗎?我寧願不循環每次輸出流,因爲它會導致程序顯着減慢。

private void printProcessOutput(Process process){ 
     BufferedReader reader = 
       new BufferedReader(new InputStreamReader(process.getInputStream())); 
     StringBuilder builder = new StringBuilder(); 
     String line = null; 

     try{ 
      while ((line = reader.readLine()) != null) { 
       builder.append(line); 
       builder.append(System.getProperty("line.separator")); 
      } 
     }catch(IOException e){ 
      e.printStackTrace(); 
     } 

     System.out.println(builder.toString()); 
    } 

    private void exportGIF(String dirPath) throws IOException { 
     List<String> lines = Arrays.asList("/Users/IdeaProjects/MasterFormat/MasterFormat-Java/MasterFormat/timMaster_4.1.png \"{200.0,467.0}\""); 
     Path headImageFile = Paths.get(System.getProperty("user.dir") + File.separator + "headImageInfo.txt"); 
     Files.write(headImageFile, lines, Charset.forName("UTF-8")); 

     String templatePath = dirPath + File.separator + "template.mp4"; 
     String outputPath = dirPath + File.separator; 
     String headImagePath = headImageFile.toString(); 
     String gifExportExecPath = "/Users/IdeaProjects/MasterFormat/MasterFormat-Java/MasterFormat/GIFExport"; 

     Process process = new ProcessBuilder(gifExportExecPath, "-s", templatePath, "-o", outputPath, "-h", headImagePath).start(); 

     printProcessOutput(process); 

     Files.delete(headImageFile); 
    } 

編輯

有一件事我要補充。我注意到,當我註釋掉調試方法時,它會在不到10分鐘內完成所有1000多次迭代計時,但是,當然gif不會導出(可執行文件不會運行...?不確定)。

當我包含打印輸出方法時,速度會慢很多。我試着在一夜之間運行它,但是經過183次迭代後它陷入了僵局。我試圖分析,看看它是否導致一些顛簸,但GC似乎運行良好。

+1

你寫「程序,但沒有任何錯誤」,這意味着它沒有「掛」的權利?所以這是不一樣的,我在這裏假設:http://stackoverflow.com/questions/22953760/processbuilder-process-not-running?rq=1 – dbalakirev

回答

2

您需要使用進程的輸出,否則可能會掛起。所以你不能評論printProcessOutput(process);。相反,註釋掉實際上做印刷線路:

try{ 
    while ((line = reader.readLine()) != null) { 
    //builder.append(line); 
    //builder.append(System.getProperty("line.separator")); 
    } 
} catch(IOException e){ 
    e.printStackTrace(); 
} 
//System.out.println(builder.toString()); 

我一般都用這個方法,這也重定向錯誤流:

public static void runProcess(ProcessBuilder pb) throws IOException { 
    pb.redirectErrorStream(true); 
    Process p = pb.start(); 
    BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream())); 
    String line; 
    while ((line = reader.readLine()) != null) { 
    //System.out.println(line); 
    } 
} 
+0

從Javadoc進程:「默認情況下,創建的子進程沒有它的所有標準I/O(即stdin,stdout,stderr)操作將被重定向到父進程,[...]因爲一些本地平臺僅爲標準輸入和輸出流提供有限的緩衝區大小,未及時寫入輸入流或讀取子流程的輸出流可能導致子流程阻塞,甚至死鎖。「所以是的,這個過程實際上正在等待完成,你可以得到內存泄漏而不會消耗err/out流。 –