2

它建立了以下代码,似乎运行良好:

void pipe(InputStream, OutputStream os) {
  try {
    try {
      byte[] buf = new byte[1024*16];
      int len, available = is.available();
      while ((len = is.read(buf, 0, available > 0 ? available : 1)) != -1) {
        os.write(buf, 0, len);
        available = is.available();
        if(available <= 0)
          os.flush();
      }
    } finally {
      try {
        os.flush();
      } finally {
        os.close();
      }
    }
  } finally {
    is.close();
  }
}

过去我发现如果调用is.read(buf),那么即使有数据,也会阻塞等待更多数据,直到缓冲区满。这是 TCP 数据的回显服务器,所以我的要求是在新数据到达时立即刷新。

我的第一个解决方案是低效的一次一次is.read()。后来,当这还不够好时,我正在查看可用的方法并发现is.available(). API 声明:

单次读取或跳过这么多字节不会阻塞。

所以我现在有一个很好的解决方案,但对我来说看起来很糟糕的一件事是我如何处理is.available() == 0. 在这种情况下,我只是读取一个字节作为等待新数据可用的一种方式。


将数据从 an 传输InputStream到 an的推荐方法是什么OutputStream,并在数据到达时立即刷新?上面的代码真的是正确的方法,还是我应该改变它,或者使用一些全新的代码?也许我应该使用一些较新的异步例程,或者可能有一个内置的 Java 方法?

4

1 回答 1

2

过去我发现如果调用is.read(buf),那么即使有数据,也会阻塞等待更多数据,直到缓冲区满。

不,你没有。TCP 不是那样工作的。套接字不能那样工作;而 Java 套接字不能那样工作。你误会了。

它比你想象的要简单得多:

while ((count = in.read(buffer)) > 0)
{
  out.write(buffer, 0, count);
}
out.close();
in.close();

套接字输入/输出流上没有缓冲,因此这将在读取后立即写入所有读取的内容。

在这种情况下或几乎在任何情况下调用 available() 完全是浪费时间。

这也是在 Java 中将任何类型的输入流复制到任何类型的输出流的方法。

如果您想要非阻塞代码,请使用 NIO。但我不认为你真的这样做。

于 2013-03-23T00:15:01.197 回答