找出流中有多少字节的更好方法?

时间:2013-08-26 19:33:18

标签: java apache stream streaming

目前,我依靠ObjectInputStream.available()方法告诉我流中剩余的字节数。原因 - 我正在为处理流的某些函数编写一些单元/集成测试,我只是想确保{I}完成后available()方法返回0。

不幸的是,在测试失败时(即,我已经向流发送了大约8个字节),available() == 0的断言在它应该为假时才会出现。它应该显示> 0或8字节!

我知道available()方法经典不可靠,但我认为它至少会显示一些> 0!

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

有谁知道为什么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之前永久阻塞。

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

UPDATE2

我注意到当我在copyStream方法的末尾添加writeTo.flush()时,它似乎再次起作用。嗯..为什么冲洗在这种情况下如此重要。即,为什么不使用它会导致流到perma-block?

1 个答案:

答案 0 :(得分:2)

available()方法仅返回可以读取多少字节不阻塞(可能为0)。为了查看流中是否还剩下任何字节,您必须read()read(byte[])这将返回读取的字节数。如果返回值为-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;

}