我正在使用DataInputStream从套接字读取一些字节。我有一个从流中读取的预期字节数(解码头后,我知道消息中有多少字节),它在99%的时间内都有效,但是偶尔我读取的字节数小于 len。
int numRead = dis.read(buffer, 0, len);
什么会导致numRead小于len?不是-1。我希望read的行为在流关闭或到达EOF之前一直阻塞,但是如果它是流下面的套接字,除非套接字关闭,否则应该不会发生,对吧?
是否有一种方法可以从套接字读取字节,从而始终确保您读取len个字节?
谢谢
编辑:对于一般信息流,基本上,您只需继续阅读,直到阅读完所有想要阅读的内容。对于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;
}
byte[] bytes = new byte[len];
dis.readFully(bytes);
这将返回读取的所有数据,或者抛出IOException。
while (true) {
int numRead = dis.read(buffer, 0, len);
if (numRead == -1) break;
total.append(buffer, numRead);
}
然后您需要检查Javadocs。 read()的约定是它将读取至少一个字节,并在必要时进行阻塞,直到这样做为止,或者直到发生EOS或异常为止。规范中没有任何内容表明它将读取您请求的整个长度。这就是为什么它返回长度的原因。
您可以使用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);