DataInputStream.read返回小于len

时间:2011-01-12 20:56:58

标签: java sockets inputstream datainputstream

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

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

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

是否有一种从套接字读取字节的方法,它总能确保您读取 len 字节?

由于

5 个答案:

答案 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);