找到你要的答案

Q:Providing to consumers InputStream from ProcessBuilder

Q:提供给消费者的processbuilder InputStream


I have this problem that I've stumbled upon recently.
I am using ProcessBuilder to call external process. Process can return either human readable string, or compressed content.
Code looks like this:

ProcessBuilder pb = new ProcessBuilder(args);
pb.redirectErrorStream(true);
Process p = pb.start();
p.waitFor();
return p.getInputStream();


This is ok for small input, but for larger one process blocks, waiting for the buffer to be emptied. Consumer code is already implemented, so is there another way to retrun from this function with an InputStream?


I have this problem that I've stumbled upon recently.
I am using ProcessBuilder to call external process. Process can return either human readable string, or compressed content.
Code looks like this:

ProcessBuilder pb = new ProcessBuilder(args);
pb.redirectErrorStream(true);
Process p = pb.start();
p.waitFor();
return p.getInputStream();


This is ok for small input, but for larger one process blocks, waiting for the buffer to be emptied. Consumer code is already implemented, so is there another way to retrun from this function with an InputStream?

answer1: 回答1:

The problem is process wont be able to write to the input stream if the consuming thread doesn't consume the values in the input stream beyond the buffer size.

if you dont want to change the consumer code , one solution i can think of is to read all the process input stream in to a StringBuffer and then return the input stream to the StringBuffer instead of the process input stream.

InputStream startProcess() {
    ProcessBuilder pb = new ProcessBuilder(args);
    pb.redirectErrorStream(true);
    Process p = pb.start();
    String dummy;
    final StringBuffer buffer = new StringBuffer();
    new Thread(new Runnable() {
       void run(){
           while(dummy = pb.getInputStream().readLine() != null) 
           buffer.append(dummy);
       }
    }).start();
    p.waitFor();
    return new ByteArrayInputStream(buffer.toString().getBytes());
}

PS: we are reading the inputstream in a different thread to avoid blocking the main thread for execution.

问题是进程将无法写入到输入流,如果消费线程不消耗的值在输入流以外的缓冲区大小。

如果你不想改变消费者的代码,一个解决方案,我能想到的就是到一个StringBuffer阅读所有过程的输入流,然后返回输入流,而不是过程的输入流的StringBuffer。

InputStream startProcess() {
    ProcessBuilder pb = new ProcessBuilder(args);
    pb.redirectErrorStream(true);
    Process p = pb.start();
    String dummy;
    final StringBuffer buffer = new StringBuffer();
    new Thread(new Runnable() {
       void run(){
           while(dummy = pb.getInputStream().readLine() != null) 
           buffer.append(dummy);
       }
    }).start();
    p.waitFor();
    return new ByteArrayInputStream(buffer.toString().getBytes());
}

PS:我们是在一个不同的线程读取InputStream避免阻塞主线程的执行。

java