Java 阅读其他流程'**无缓冲**输出流

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

我正在用java为文件转换器编写一个小GUI。文件转换器将其当前进度写入标准输出。看起来像这样:

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块。无论如何,谢谢你的忍者方法