用伪代码,这是我在做什么:
Process proc = runtime.exec(command);
processOutputStreamInThread(proc.getInputStream());
processOutputStreamInThread(proc.getErrorStream());
proc.waitFor()
但是,有时processOutputStreamInThread看不到任何输出,有时却看到。大致而言,该方法创建BufferedInputStream命令输出的a并将其发送到记录器。
根据我所看到的,我猜,command不用都它的输出排入流美联储getInputStream()和getErrorStream(),从而使流是空的。
我的审判结果是以下问题:
(1)waitFor()在java.lang.Process中,是否要求执行程序的输出在返回之前已被读取?
该文档仅说明:
使当前线程在必要时等待,直到此Process对象表示的进程终止。如果子进程已经终止,则此方法立即返回。如果子进程尚未终止,则调用线程将被阻塞,直到子进程退出。
(2) 在什么条件下,由getInputStream和提供的流getErrorStream需要关闭,和/或它们是自动关闭的?
该文档仅说明:
获取子流程的错误流。该流从此Process对象表示的过程的错误输出流中获取通过管道传输的数据。
实施说明:缓冲输入流是个好主意。
一个用户报告说他必须自己关闭流,但是我至少有部分时间遇到异常,表明我尝试关闭流时已经关闭。
编辑: 更改getOutputStream为getInputStream,现在位于上方。
解决: 问题最终是,在某些情况下,用于处理输出流的线程要到我的短暂进程完成后才能运行,从而导致输入流不提供任何数据。
waitFor没有等待已执行程序的输出。而是,程序可以运行并终止,然后才能收集任何输出。
我使用线程是因为我不确定要在标准错误和标准输出上获得多少输出,并且我希望能够同时处理这两个输出,而不会阻塞一个或另一个,只要其中一个具有可用数据即可。但是,由于我的线程无法始终如一地读取已执行程序的输出,因此这不是解决方案。
我最终的代码看起来像这样:
ProcessBuilder pb = new ProcessBuilder(cmdargs);
pb.redirectErrorStream(true);
Process proc = pb.start();
processOutputStream(proc.getInputStream());
proc.waitFor()