【问题标题】:How to force java OutputStreamWriter to actually write a single byte?如何强制 java OutputStreamWriter 实际写入单个字节?
【发布时间】:2019-03-17 16:14:26
【问题描述】:

我正在尝试从 Java 运行一个简单的 echo 程序(使用 ProcessBuilder),有一个无限循环,我从用户那里获取输入(使用 Scanner)。然后我使用OutputStreamWriter 将其写入进程的标准输入,我希望看到相同的字符串通过标准输出回显,但除非我关闭流(我不想这样做)或者我写一个长字符串。即使在调用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,这让事情变得更加有趣。

【问题讨论】:

  • cmd 变量中有什么内容?
  • {a.exe}:它是一个程序,它只会回显你输入的任何内容。 (while(1){ fgets(buf, MAX, stdin); printf("string is: %s", buf); })

标签: java io outputstream


【解决方案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

【讨论】:

  • 我添加了“writer.write(System.lineSeparator());”但它仍然不起作用。我还尝试更改“writer.write(input);”到 "writer.write(input+"\n");"仍然,没有工作。
  • 另外,这不是问题,因为即使不使用行分隔符,如果您输入很长的字符串,它也可以工作。所以我猜问题出在刷新上,因为即使你有一个短字符串和一个换行符,它仍然不起作用,这可能意味着它没有被刷新到“a.exe”
【解决方案2】:

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

【讨论】:

    猜你喜欢
    • 2012-07-17
    • 2011-11-28
    • 1970-01-01
    • 2012-12-23
    • 1970-01-01
    • 2011-01-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多