DataInputStream.read返回小于len

问题描述 投票:6回答:5

我正在使用DataInputStream从套接字读取一些字节。我有一个从流中读取的预期字节数(解码头后,我知道消息中有多少字节),它在99%的时间内都有效,但是偶尔我读取的字节数小于 len

int numRead = dis.read(buffer, 0, len);

什么会导致numRead小于len?不是-1。我希望read的行为在流关闭或到达EOF之前一直阻塞,但是如果它是流下面的套接字,除非套接字关闭,否则应该不会发生,对吧?

是否有一种方法可以从套接字读取字节,从而始终确保您读取len个字节?

谢谢

java sockets inputstream datainputstream
5个回答
12
投票

编辑:对于一般信息流,基本上,您只需继续阅读,直到阅读完所有想要阅读的内容。对于DataInput(例如DataInputStream)的实现,应使用Peter Lawrey建议的readFully。考虑此答案的其余部分与仅拥有InputStream的一般情况有关。

[完全任何类型的InputStream给您的数据都比您要的要少,即使有更多的数据正在进行中。您应该始终针对这种可能性进行编码-可能是ByteArrayInputStream例外。 (当然,如果返回的数据[[left少于您的要求,返回的数据仍然会比请求的少。)

这是我正在谈论的那种循环:byte[] data = new byte[messageSize]; int totalRead = 0; while (totalRead < messageSize) { int bytesRead = stream.read(data, totalRead, messageSize - totalRead); if (bytesRead < 0) { // Change behaviour if this isn't an error condition throw new IOException("Data stream ended prematurely"); } totalRead += bytesRead; }

8
投票
byte[] bytes = new byte[len]; dis.readFully(bytes);

这将返回读取的所有数据,或者抛出IOException。


0
投票
while (true) { int numRead = dis.read(buffer, 0, len); if (numRead == -1) break; total.append(buffer, numRead); }

0
投票
我希望读取的行为阻塞直到流关闭或已达到EOF。
然后您需要检查Javadocs。 read()的约定是它将读取至少一个字节,并在必要时进行阻塞,直到这样做为止,或者直到发生EOS或异常为止。规范中没有任何内容表明它将读取您请求的整个长度。这就是为什么它返回长度的原因。

0
投票
是否有一种方法可以从套接字读取字节,从而始终确保您读取len字节?
您可以使用Apache Commons IOUtils,它们具有一种完全可以满足您需要的方法:

byte[] buf = new byte[BUFFER_SIZE]; int length; do { length = IOUtils.read(inputStream, buf); if (length > 0) { //do something with buf } } while (length == BUFFER_SIZE);

© www.soinside.com 2019 - 2024. All rights reserved.