Java exec方法,如何正确处理流

Java产生和使用外部进程的流(IO)的正确方法是什么?据我所知,由于可能的缓冲区大小有限,因此应在与生成进程输入并行的线程中使用java结束输入流(进程输出)。

但是我不确定我是否最终需要与这些使用者线程进行同步,或者仅等待进程退出以使用waitFor方法就足够了,以确保所有进程输出实际上都被消耗了?IE是否有可能,即使进程退出(关闭其输出流),流的Java端仍存在未读数据?waitFor实际如何知道该过程何时完成?对于有问题的进程,

EOF (关闭其输入流的java末尾)表示退出。

我当前处理流的解决方案如下

public class Application {

private static final StringBuffer output = new StringBuffer();

private static final StringBuffer errOutput = new StringBuffer();

private static final CountDownLatch latch = new CountDownLatch(2);

public static void main(String[] args) throws IOException, InterruptedException {

Process exec = Runtime.getRuntime().exec("/bin/cat");

OutputStream procIn = exec.getOutputStream();

InputStream procOut = exec.getInputStream();

InputStream procErrOut = exec.getErrorStream();

new Thread(new StreamConsumer(procOut, output)).start();

new Thread(new StreamConsumer(procErrOut, errOutput)).start();

PrintWriter printWriter = new PrintWriter(procIn);

printWriter.print("hello world");

printWriter.flush();

printWriter.close();

int ret = exec.waitFor();

latch.await();

System.out.println(output.toString());

System.out.println(errOutput.toString());

}

public static class StreamConsumer implements Runnable {

private InputStream input;

private StringBuffer output;

public StreamConsumer(InputStream input, StringBuffer output) {

this.input = input;

this.output = output;

}

@Override

public void run() {

BufferedReader reader = new BufferedReader(new InputStreamReader(input));

String line;

try {

while ((line = reader.readLine()) != null) {

output.append(line + System.lineSeparator());

}

} catch (IOException e) {

// TODO Auto-generated catch block

e.printStackTrace();

} finally {

try {

reader.close();

} catch (IOException e) {

// TODO Auto-generated catch block

e.printStackTrace();

} finally {

latch.countDown();

}

}

}

}

}

是否有必要在此处使用锁存器,或waitFor暗示所有输出已被使用?另外,如果输出没有结束/包含新行,会readLine丢失输出还是仍然读取所有剩余内容?读取null是否意味着进程已关闭它的流的末尾-

是否还有其他可能读取null的情况?

处理流的正确方法是什么,是否可以做得比示例更好?

回答:

waitFor表示进程已结束,但是您不能确定从stdout和stderr收集字符串的线程也完成了,因此使用闩锁是朝着正确方向迈出的一步,但不是最佳选择。您不必等待闩锁,而可以直接等待线程:

Thread stdoutThread = new Thread(new StreamConsumer(procOut, output)).start();

Thread stderrThread = ...

...

int ret = exec.waitFor();

stdoutThread.join();

stderrThread.join();

顺便说一句,将行存储在StringBuffers中是无用的工作。请ArrayList<String>改用,不做任何转换就将行放置在那里,最后以循环的方式检索它们。

以上是 Java exec方法,如何正确处理流 的全部内容, 来源链接: utcz.com/qa/403384.html

回到顶部