我希望能够从java执行外部命令,例如" ls",并将输出,输出和错误流作为字符串,并实时获取,并按顺序生成了。
因此,如果命令的输出类似于:
blah <- to stdout
foo <- to stderr
bar <- to stdout
然后,理想情况下,我希望输出字符串和实时输出看起来像:
blah
foo
bar
天真的方法产生:
blah
bar
(即没有stderr输出)
或:
blah
bar
foo
(即重新排列顺序,以便stdout和stderr消息不会相互交织)。
答案 0 :(得分:3)
使用ProcessBuilder
并设置redirectErrorStream(true)
。
答案 1 :(得分:3)
这并非总是可行。
如果您使用ProcessBuilder
API,则可以将stdout
和stderr
流合并为一个(使用redirectErrorStream(true)
),这样您就可以在一个内容中读取两个输出InputStream
。但这意味着您无法判断数据最初来自哪个流。
如果您将stdout
和stderr
视为两个流,则需要NIO或两个Java线程。在这两种情况下,处理一个输出将阻止另一个输出(或者更确切地说,不会及时处理另一个流)。这将导致交换线。
如果子进程没有刷新输出并且你使用管道,那么这会变得更糟,因为stdout
将以4KB块的形式发送到你的进程,而stderr
通常会逐行到达线。
我担心没有独立于平台的解决方法。如果您只需要一个适用于Unix的解决方案,您可以使用伪TTY(man 4 pty
)来模拟shell,但由于您需要调用OS函数,因此很难从Java设置。
一种方法可能是使用Perl或类似方法在PTY中运行您的命令(这会导致stdout变为行缓冲),从那里读取stdout和stderr并为每行添加1
stdout和{{ 1}}对于stderr。
答案 2 :(得分:1)
我建议您使用Apache commons exec API,因为它们是更复杂的API。
请参阅DefaultExecutor:您可以: