命令外壳上的Java进程之间的管道无法可靠工作 [英] Pipe between java processes on command shell not reliable working

查看:84
本文介绍了命令外壳上的Java进程之间的管道无法可靠工作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在两个Java程序之间传递文本.为了简单起见,我提供以下代码:

I'm trying to pipe text between two java programs. For the sake of simplicity I'm presenting this code:

import java.io.DataInputStream;
import java.io.IOException;

public class Test {
    public static void main(String[] args) throws IOException {
        DataInputStream stdin = new DataInputStream(System.in);
        String completeText = ""; 

        while (stdin.available() > 0) {
            byte[] tempByte = { stdin.readByte() };
            completeText += new String(tempByte);
        }

        System.out.println(completeText);
    }
}

在linux或Windows上执行以下操作时,似乎忽略了该文本,好像管道阻塞或丢失得非常随意.有时一切顺利,有时没有:

When doing the following on linux or windows, the text seems to get omitted as if the pipe was blocking or lost quite random. Sometimes everything gets through, sometimes not:

echo "omg wtf" | java Test | java Test

对此有何想法?看来,cpu越慢,文本通过的频率就越高.从java System.out.println()传递输入时,可用"是否由于任何原因返回错误的结果?

Any ideas on this? The slower the cpu the more often the text gets through, it seems. Is "available" returning the wrong result for any reason when the input is piped from java System.out.println()?

干杯!

推荐答案

首先,available()方法不是确定流是否已耗尽的可靠方法.通过检查read()方法的返回值来可靠地指示流结束(<0表示流结束).

First, The available() method is not a reliable way to determine whether a stream is exhausted. A reliable indication to an end-of-stream is by checking the return value of the read() method (< 0 means end-of-stream).

简而言之,如果流暂时为空,则available()可以返回false(这将终止循环).如果管道仍处于活动状态,则管道另一端的进程向其中写入一些字节后,这种情况将改变.为确保已读取所有数据,您需要检查数据流的结尾.

In short, available() can return false (which will terminate the loop), if the stream is momentarily empty. If the pipe is still active, this situation will change as soon as the process on the other end of the pipe writes some bytes into it. To be sure that all data was read you need to check for end-of-stream.

第二,如果您想读取字符(并将它们连接成字符串),则应该从

Second, if you want to read characters (and concatenate them into a string) you should read characters from a Reader (and not bytes from a stream). This will allow your code to handle unicode characters.

第三,如果使用

Third, concatenation of large chunks of characters is will be faster if you use a StringBuilder (rather than a plain String).

最后,如果只需要读取字节,则可以直接使用输入流(无需使用DataInputStream进行包装).

Finally, if you only need to read bytes, you can use the input-stream directly (no need to wrap it with a DataInputStream).

这是我的写法:

Reader r = new InputStreamReader(System.in);
StringBuilder sb = new StringBuilder();
while(true) {
  int ch = r.read();
  if(ch < 0)
    break;
  sb.append((char) ch);
}

System.out.println(sb.toString());

这篇关于命令外壳上的Java进程之间的管道无法可靠工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆