【发布时间】:2013-08-26 19:33:17
【问题描述】:
目前,我依靠ObjectInputStream.available() 方法告诉我一个流中还剩下多少字节。原因——我正在对某些处理流的函数编写一些单元/集成测试,我只是想确保available() 方法在我完成后返回 0。
不幸的是,在测试失败时(即,我已经在流中发送了大约 8 个字节),我对 available() == 0 的断言在它应该为假的时候出现了。它应该显示 >0 或 8 个字节!
我知道 available() 方法在经典上是不可靠的,但我认为它至少会显示 > 0!
是否有更可靠的方法来检查流是否为空(毕竟这是我的主要目标)?也许在 Apache IO 域或其他一些库中?
有人知道为什么available() 方法如此不可靠吗?有什么意义呢?或者,有没有特定的、正确的使用方法?
更新:
所以,正如你们中的许多人可以从 cmets 中看到的那样,我面临的主要问题是,在流的一端,我发送了一定数量的字节,但在另一端,并非所有字节都到达!
具体来说,我在一端发送 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
我注意到,当我在 copyStream 方法的末尾添加 writeTo.flush() 时,它似乎又可以工作了。嗯..为什么在这种情况下冲洗如此重要。即,为什么不使用它会导致流永久阻塞?
【问题讨论】:
-
你怎么知道流中有
x字节而不读取它?available()方法明确声明返回可以不阻塞读取的字节数。如果要读取更多字节,则需要阻塞。 -
您应该检查
InputStream#read()返回-1以查看是否已到达流的末尾。 -
@SotiriosDelimanolis,
available()不应该至少给出一个返回值 1 以表明在阻塞时至少有 1 个字节要读取? -
如果它可以不阻塞地读取 1 个字节,它会这样说。 它不知道在没有读取它们的情况下阻塞时可以读取多少字节(即到达流的末尾)。
-
我明白了……这很有趣。在我期望流中没有任何内容的情况下,我实际上正在读取一个字节 0x79,之后,
.read()方法会无限期阻塞......这些症状是否让您想起了什么?
标签: java apache stream streaming