gpt4 book ai didi

Java - 如果数据太小,刷新进程的 OutputStream 不会立即发送数据

转载 作者:行者123 更新时间:2023-12-01 14:24:18 25 4
gpt4 key购买 nike

我正在从 Java 启动一个外部进程并通过 process.getInputStream() 获取它的标准输入、标准输出和标准错误。等等。我的问题是:当我想将数据写入我的输出流(proc 的标准输入)时,直到我实际调用 close() 才会发送它。在流上。我明确调用 flush() .

我做了一些实验,发现如果我增加发送的字节数,它最终会通过。在我的系统上,神奇的数字是 4058 字节。

为了测试,我将数据发送到一个 perl 脚本,如下所示:

#!/usr/bin/perl
use strict;
use warnings;

print "Perl starting";

while(<STDIN>) {
print "Perl here, printing this: $_"
}

现在,这是java代码:

import java.io.InputStream;
import java.io.IOException;
import java.io.OutputStream;

public class StreamsExecTest {


private static String readInputStream(InputStream is) throws IOException {
int guessSize = is.available();
byte[] bytes = new byte[guessSize];
is.read(bytes); // This call has side effect of filling the array
String output = new String(bytes);
return output;
}

public static void main(String[] args) {

System.out.println("Starting up streams test!");

ProcessBuilder pb;
pb = new ProcessBuilder("./test.pl");


// Run the proc and grab the streams
try {
Process p = pb.start();
InputStream pStdOut = p.getInputStream();
InputStream pStdErr = p.getErrorStream();
OutputStream pStdIn = p.getOutputStream();


int counter = 0;
while (true) {

String output = readInputStream(pStdOut);
if (!output.equals("")) {
System.out.println("<OUTPUT> " + output);
}

String errors = readInputStream(pStdErr);
if (!errors.equals("")) {
System.out.println("<ERRORS> " + errors);
}

if (counter == 50) {
// Write to the stdin of the execed proc. The \n should
// in turn trigger it to treat it as a line to process
System.out.println("About to send text to proc's stdin");
String message = "hello\n";

byte[] pInBytes = message.getBytes();
pStdIn.write(pInBytes);
pStdIn.flush();
System.out.println("Sent " + pInBytes.length + " bytes.");

}

if (counter == 100) {
break;
}

Thread.sleep(100);
counter++;
}
// Cleanup
pStdOut.close();
pStdErr.close();
pStdIn.close();
p.destroy();

} catch (Exception e) {
// Catch everything
System.out.println("Exception!");
e.printStackTrace();
System.exit(1);
}

}
}

所以当我运行这个时,我实际上什么也没得到。如果在调用 flush() 之后立即, 我调用 close()在 pStdIn 上,它按预期工作。不过,这不是我想要的;我希望能够持续保持流打开并在我喜欢的时候写入它。如前所述,如果消息为 4058 字节或更大,则无需 close() 即可。 .

操作系统(在 64 位 Linux 上运行,具有 64 位 Sun JDK 的值(value))是否在发送数据之前对其进行缓冲?我可以看到 Java 无法真正控制它,一旦 JVM 进行系统调用以写入管道,它所能做的就是等待。不过还有一个谜团:

Perl 脚本在进入 while 之前打印行。环形。由于我在 Java 循环的每次迭代中检查来自 Perl 标准输出的任何输入,我希望在第一次运行循环时看到它,看到尝试从 Java->Perl 发送数据,然后什么也没有。但实际上,当写入输出流时,我实际上只看到来自 Perl 的初始消息(在该 OUTPUT 消息之后)。有什么我不知道的阻塞吗?

非常感谢任何帮助!

最佳答案

你还没有告诉 Perl 使用无缓冲的输出。查看 perlvar并搜索 $|用于设置无缓冲模式的不同方法。本质上,其中之一:

HANDLE->autoflush( EXPR )
$OUTPUT_AUTOFLUSH
$|

关于Java - 如果数据太小,刷新进程的 OutputStream 不会立即发送数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11533601/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com