如何强制java OutputStreamWriter实际写一个字节?

问题描述 投票:1回答:2

我试图从Java运行一个简单的echo程序(使用ProcessBuilder),有一个无限循环,我从用户输入(使用Scanner)。然后我使用OutputStreamWriter将它写入进程的stdin,我希望看到相同的字符串通过stdout回显,但它不会,除非我关闭流(我不想)或我写了一个长串。当调用flush时,如果字符串很短(比如1个字符)则不起作用。

即使对于单个字符(短)字符串,我们如何强制刷新?

ProcessBuilder pb = new ProcessBuilder(cmd);
Process p = pb.start();
BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));
OutputStream stdin = p.getOutputStream();
OutputStreamWriter writer = new OutputStreamWriter(stdin);
Scanner scanner = new Scanner(System.in);
String line;
while (true) {
    String input = scanner.nextLine();
    if (input.equals("q"))
        break;
    writer.write(input+"\n");
    writer.flush();
    // writer.close(); (uncommenting this makes it work once, then throw error)
    line = br.readLine();
    System.out.println(line);
}

编辑3/18:我已经尝试过windows sysinternals工具来跟踪写入系统调用,它确实看起来我的猜测是正确的,除非它是一个长字符串(或除非你关闭流),否则刷新不起作用。 编辑3/19:我发现了这个:Does fgets() locks stdout preventing printf让事情变得更有趣。

java io outputstream
2个回答
1
投票

问题在于与a.exe的互动。

a.exe使用fgets。当读取(n-1)个字符,读取换行符或达到文件结尾时(以先到者为准),它会停止。

你没有向a.exe推新行,因此fgets只能用EOF完成,当你关闭流时会发生这种情况。

您可以从Java推送行尾,也可以在C端使用另一个读取函数。

要推送终端,您可以使用:

writer.write(System.lineSeparator());

见:https://www.tutorialspoint.com/c_standard_library/c_function_fgets.htm


0
投票

由于这个问题,问题终于得到了解决: Does fgets() locks stdout preventing printf 所以这个问题实际上不是java的错,它是windows的特性之一,这里因为我已经将流连接到stdin和stdout,而我没有关闭stdin,它不会写入stdout。 所以解决方案:1)在“a.exe”端刷新stdout。或2)只是不要使用两个流。例如,在“a.exe”端,而不是stdout,写入文件,并在java端使用该文件。 (1)是更好的选择,如果您有权访问“a.exe”,但这可能是您无法访问的外部程序。

© www.soinside.com 2019 - 2024. All rights reserved.