Java 阅读其他流程'**无缓冲**输出流
我正在用java为文件转换器编写一个小GUI。文件转换器将其当前进度写入标准输出。看起来像这样:Java 阅读其他流程'**无缓冲**输出流,java,process,stream,stdout,unbuffered,Java,Process,Stream,Stdout,Unbuffered,我正在用java为文件转换器编写一个小GUI。文件转换器将其当前进度写入标准输出。看起来像这样: ProcessBuilder builder = new ProcessBuilder("..."); builder.redirectErrorStream(true); Process proc = builder.start(); InputStream stream = proc.getInputStream(); byte[] b = new byte[32]; int length; w
ProcessBuilder builder = new ProcessBuilder("...");
builder.redirectErrorStream(true);
Process proc = builder.start();
InputStream stream = proc.getInputStream();
byte[] b = new byte[32];
int length;
while (true) {
length = stream.read(b);
if (length < 0) break;
// processing data
}
BufferedInputStream stream = new BufferedInputStream(proc.getInputStream(), 32);
Flow_1.wav:28%完成,比率=0447
我想在进度条中说明这一点,因此我阅读流程的标准如下:
ProcessBuilder builder = new ProcessBuilder("...");
builder.redirectErrorStream(true);
Process proc = builder.start();
InputStream stream = proc.getInputStream();
byte[] b = new byte[32];
int length;
while (true) {
length = stream.read(b);
if (length < 0) break;
// processing data
}
BufferedInputStream stream = new BufferedInputStream(proc.getInputStream(), 32);
或者这个:
BufferedReader reader = new BufferedReader(new InputStreamReader(proc.getInputStream()), 32);
但两者都没有改变什么
然后我发现了这个:(在第87行附近)
似乎流程类的实现方式是将流程的stdout管道化到一个文件。那么什么proc.getInputStream()代码>实际上是将流返回到文件。这个文件似乎是用4KB的缓冲区写的
有人知道这种情况下的解决方法吗?我只想立即得到进程的输出
编辑:正如Ian Roberts所建议的,我还尝试将转换器的输出通过管道传输到stderr流中,因为该流似乎没有包装在BufferedInputStream
中。还是4k块
另一件有趣的事情是:我实际上没有得到4096字节,但大约还有5个。很抱歉,FileInputStream
本身是本机缓冲的。查看链接到进程标准输出流的代码会被包装在BufferedInputStream
中,但其标准错误仍然没有缓冲。因此,一种可能不是直接执行转换器,而是执行一个shell脚本(如果您在Windows上,则执行Windows等效脚本),将转换器的stdout发送到stderr:
ProcessBuilder builder = new ProcessBuilder("/bin/sh", "-c",
"exec /path/to/converter args 1>&2");
不要redirectErrorStream
,然后从proc.getErrorStream()
读取,而不是proc.getInputStream()
可能您的转换器已经在使用stderr进行进度报告,在这种情况下,您不需要脚本位,只需关闭redirectErrorStream()
。如果转换器程序同时写入stdout和stderr,那么您还需要生成第二个线程来使用stdout(脚本方法通过将所有内容发送到stderr来解决这个问题)。这并不是说它改变了您的问题,而是java没有将数据流式传输到文件中。文件描述符是操作系统描述过程输入/输出流的方式。它们不一定与实际文件相关(尽管可能)。通常,stdout已经被写入它的进程缓冲,因此如果是这种情况,如果不能更改另一个进程,您就没有机会了。该进程需要更频繁地关闭缓冲或调用flush()。@PhilippWendler:转换器的标准输出肯定比每4KB刷新一次(从终端运行时)更频繁。您认为当stdout未发送到控制台时,\n处的自动刷新会关闭吗?@R2-D2虽然技术上可行,但我不希望应用程序会这样做。我知道操作系统也可能做缓冲,但我不知道这方面的任何细节。也许可以研究一下这个方向?你可以编写一个小的C程序来启动你的进程并读取输入,看看这是否是一个Java特有的问题。但这不起作用。还是4k块。无论如何,谢谢你的忍者方法