我正在使用DataInputStream从套接字读取一些字节。我有一个从流中读取的预期字节数(在解码头之后,我知道消息中有多少字节)它在99%的时间内工作但偶尔我会读取的字节数小于 LEN 。
int numRead = dis.read(buffer, 0, len);
什么可能导致numRead小于len?它不是-1。我希望read的行为在流被关闭或达到EOF之前阻塞,但如果它是一个基于流的套接字,除非套接字关闭,否则这不应该发生,对吧?
是否有一种从套接字读取字节的方法,它总能确保您读取 len 字节?
由于
答案 0 :(得分:11)
编辑:对于一般流,你只需继续阅读,直到你已经阅读了你想要的一切,基本上。对于DataInput
的实施(例如DataInputStream
),您应该使用readFully
,正如Peter Lawrey所建议的那样。请考虑此答案的其余部分与您只有InputStream
的一般情况相关。
对于任何类型的InputStream
,完全合理地为您提供的数据少于您要求的数据,即使有更多的数据正在进行中。你应该总是为这种可能性编码 - 可能除了ByteArrayInputStream
。 (当然,如果左的数据少于您要求的数据,那么仍然可以返回的数据少于所请求的数据。)
这是我正在谈论的那种循环:
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;
}
答案 1 :(得分:8)
您可以这样使用DataInputStream。
byte[] bytes = new byte[len];
dis.readFully(bytes);
这将返回所有读取的数据或抛出IOException。
答案 2 :(得分:0)
读取每次都返回当时可用的位和-1完成时返回,通常应该这样做
while (true) {
int numRead = dis.read(buffer, 0, len);
if (numRead == -1) break;
total.append(buffer, numRead);
}
答案 3 :(得分:0)
我希望读到的行为 阻止直到流关闭或 达到了EOF。
然后你需要检查Javadocs。 read()的契约是它将读取至少一个字节,必要时阻塞直到它完成,或者直到EOS或异常发生。规范中没有任何内容表明它会读取您请求的整个长度。这就是它返回长度的原因。
答案 4 :(得分: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);