2010-11-15 181 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