2010-11-15 188 views
1

在java 6 webapp中,我試圖從執行的命令中檢索大量的輸出。我在javaworld article上「借/偷」了它。我面臨的問題是,由於輸出被截斷,長度似乎超過了尺寸限制。我已經將數據輸出到一個文件,所以我可以看到返回的大小,這正好是32K(32768)。我已經嘗試過更改緩衝區的默認大小(請參閱BufferedReader構造函數),但是我沒有觀察到任何返回數據長度的變化,無論緩衝區大小(從小到大) 。超過了BufferedReader的大小限制?

任何意見將非常感謝!

public class StreamGobbler extends Thread { 

private InputStream is; 
private String type; 
private List<String> output; 

public StreamGobbler(InputStream is, String type) { 
    this.is = is; 
    this.type = type; 
} 

@Override 
public void run() { 
    try { 
     InputStreamReader isr = new InputStreamReader(is); 
     BufferedReader br = new BufferedReader(isr); 
     String line = null; 
     this.output = new ArrayList<String>(); 
     while ((line = br.readLine()) != null) { 
      this.getOutput().add(line + "\n"); 
      System.out.println(type + ">" + line); 
     } 
     br.close(); 
    } catch (IOException ioe) { 
     System.err.println("ERROR: " + ioe.getMessage()); 
    } 
} 

/** 
* @return the output 
*/ 
public List<String> getOutput() { 
    return output; 
} 

}

public class JobClassAds { 

private String CONDOR_HISTORY = "condor_history"; 
private String CONDOR_HISTORY_XML = CONDOR_HISTORY + " -xml"; 
private String CONDOR_HISTORY_LONG = CONDOR_HISTORY + " -long"; 

public String getHistory() { 
    try { 
     Runtime runtime = Runtime.getRuntime(); 
     String exec = CONDOR_HISTORY_LONG; 
     Process process = runtime.exec(exec); 
     System.out.println("Running " + exec + " ..."); 

     // Error message 
     StreamGobbler errGobbler = new StreamGobbler(process.getErrorStream(), "ERROR"); 

     // Output 
     StreamGobbler outGobbler = new StreamGobbler(process.getInputStream(), "OUTPUT"); 

     Thread outThread = new Thread(outGobbler); 
     Thread errThread = new Thread(errGobbler); 

     outThread.start(); 
     errThread.start(); 

     outThread.join(); 
     errThread.join(); 

     /* 
     String line = null; 

     while ((line = input.readLine()) != null) { 
      System.out.println(line); 
      content.append(line); 
     } 

     * 
     */ 

     int exitVal = process.waitFor(); 

     List<String> output = outGobbler.getOutput(); 
     String inputString = ""; 
     for (String o : output) { 
      inputString += o; 
     } 

     System.out.println(exec + " Exited with error code " + exitVal); 

     BufferedWriter out = new BufferedWriter(new FileWriter("/tmp/history_result.xml")); 
     out.write(inputString); 
     out.close(); 
     return inputString; 

    } catch (Exception e) { 
     System.err.println(e.getMessage()); 
     return null; 
    } 
} 
+0

更改BufferedReader上的緩衝區大小隻會改變它在內部使用的臨時存儲量。 BufferedReader沒有大小限制,因此您應該能夠使用此代碼讀取整個輸出。你有沒有檢查condor_history - long本身產生完整的輸出,並不停在32K? – Zarkonnen 2010-11-15 23:09:05

+0

謝謝澄清。運行該命令將返回完整的輸出。 – samiam 2010-11-16 14:45:27

回答

0

的問題是不與BufferedReader的緩衝區大小。

我認爲真正的原因是外部命令正在做的事情。我懷疑它沒有刷新它的標準輸出流。請注意,您「吞噬」但不輸出命令的stderr流。這就是你可能找到證據指出問題的真正原因的地方。


順便說一下,您正在使用StreamGobbler類以次優方式。它擴展Thread所以使用預期的方法是:

SteamGobbler sg = new StreamGobbler(...); 
    sg.start(); 
    sg.join(); 

,但你實際上這樣做:

SteamGobbler sg = new StreamGobbler(...); 
    Thread th = new Thread(sg); 
    th.start(); 
    th.join(); 

它的工作原理......但僅僅是因爲一個Thread是,一個Runnable

+0

謝謝。運行cli會返回完整的輸出。欣賞關於主題的反饋。原來我就是這樣做的,所以我已經回覆了它。 – samiam 2010-11-16 14:47:47

+0

@samiam - *「運行cli返回完整的輸出。」*。這並不意味着它不是外部命令的錯。命令行參數或環境變量可能不同,等等。您需要檢查stderr內容。 – 2010-11-16 21:58:09