2

目前,我依靠该ObjectInputStream.available()方法来告诉我流中还剩下多少字节。原因——我正在对某些处理流的函数编写一些单元/集成测试,我只是想确保该available()方法在完成后返回 0。

不幸的是,在测试失败时(即,我已经在流中发送了大约 8 个字节),我的断言 foravailable() == 0在它应该是假的时候是真的。它应该显示 >0 或 8 个字节!

我知道该available()方法在经典上是不可靠的,但我认为它至少会显示 > 0!

有没有更可靠的方法来检查流是否为空(毕竟这是我的主要目标)?也许在 Apache IO 域或其他一些库中?

有谁知道为什么这种available()方法非常不可靠?有什么意义呢?或者,是否有特定的、正确的使用方法?


更新:

所以,正如你们中的许多人可以从评论中看到的那样,我面临的主要问题是,在流的一端,我发送了一定数量的字节,但在另一端,并不是所有的字节都到达了!

具体来说,我在一端发送 205498 字节,而在另一端只收到 204988,始终如一。我在套接字中的线程之间控制此操作的双方,但这应该没关系。

这是我为收集所有字节而编写的代码。

  public static int copyStream(InputStream readFrom, OutputStream writeTo, int bytesToRead)
      throws IOException {

    int bytesReadTotal = 0, bytesRead = 0, countTries = 0, available = 0, bufferSize = 1024 * 4;

    byte[] buffer = new byte[bufferSize];

    while (bytesReadTotal < bytesToRead) {

      if (bytesToRead - bytesReadTotal < bufferSize)
        buffer = new byte[bytesToRead - bytesReadTotal];

      if (0 < (available = readFrom.available())) {
        bytesReadTotal += (bytesRead = readFrom.read(buffer));
        writeTo.write(buffer, 0, bytesRead);
        countTries = 0;

      } else if (countTries < 1000)
        try {
          countTries++;
          Thread.sleep(1L);

        } catch (InterruptedException ignore) {}
      else

        break;
    }

    return bytesReadTotal;
  }

我把 countTries 变量放在那里只是为了看看会发生什么。即使没有 countTires,它也会在到达 BytesToRead 之前永远阻塞。

什么会导致流突然无限期地阻塞?我知道在另一端它完全发送字节(因为它实际上使用了相同的方法,我看到它最终完成了完整的 BytesToRead 匹配 bytesReadTotal 的功能。但接收器没有。事实上,当我看看数组,它们也完全匹配到最后。

更新2

我注意到,当我writeTo.flush()在 copyStream 方法的末尾添加 a 时,它似乎又可以工作了。嗯..为什么在这种情况下冲洗如此重要。即,为什么不使用它会导致流永久阻塞?

4

1 回答 1

2

available()方法只返回可以读取多少字节而不阻塞(可能为0)。为了查看流中是否还有任何字节,您必须read()read(byte[])which 将返回读取的字节数。如果返回值是,-1那么您已经到达文件末尾。

这个小代码片段将循环通过 InputStream 直到它到达末尾(read() 返回 -1)。我认为它永远不会返回 0,因为它应该阻塞,直到它可以读取 1 个字节或发现没有什么可以读取(因此返回 -1)

int currentBytesRead=0;
int totalBytesRead=0;
byte[] buf = new byte[1024];

while((currentBytesRead =in.read(buf))>0){
        totalBytesRead+=currentBytesRead;

}
于 2013-08-26T19:50:15.800 回答