DataInputStream.read 返回小于 len

发布于 2024-10-12 04:18:44 字数 344 浏览 8 评论 0原文

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

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

什么可能导致 numRead 小于 len?它不是-1。我希望 read 的行为会阻塞,直到流关闭或达到 EOF,但如果它是流底层的套接字,除非套接字关闭,否则这种情况不会发生,对吧?

有没有一种方法可以从套接字读取字节,并且始终确保读取 len 字节?

谢谢

I am using DataInputStream to read some bytes from a socket. I have a expected number of bytes to read from the stream (after decoding a header, I know how many bytes are in the message) It works 99% of the time but occasionally I will have the number of bytes read be less than len.

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

What could cause numRead to be less than len? It's not -1. I would expect the behavior of read to block until the stream is closed or EOF is reached, but if it's a socket underlying the streams this shouldn't happen unless the socket closes, right?

Is there a way of reading bytes from a socket that will always ensure that you read len bytes?

Thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

一抹微笑 2024-10-19 04:18:44

编辑:对于一般流,您只需继续阅读,直到读完您想要的所有内容为止。对于 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;
}

EDIT: For a general stream, you just keep reading until you've read everything you want to, basically. For an implementation of DataInput (such as DataInputStream) you should use readFully, as suggested by Peter Lawrey. Consider the rest of this answer to be relevant for the general case where you just have an InputStream.

It's entirely reasonable for an InputStream of any type to give you less data than you asked for, even if more is on its way. You should always code for this possibility - with the possible exception of ByteArrayInputStream. (That can still return less data than was requested, of course, if there's less data left than you asked for.)

Here's the sort of loop I'm talking about:

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;
}
奢欲 2024-10-19 04:18:44

您可以通过这种方式使用 DataInputStream。

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

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

You can use DataInputStream this way.

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

This will either return with all the data read or throw an IOException.

眼趣 2024-10-19 04:18:44

read 每次都会返回当时可用的位,完成后返回 -1,您通常应该这样做

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

read returns each time with the bits that were available at that time and -1 when done, you are typically supposed to do

while (true) {
  int numRead = dis.read(buffer, 0, len);
  if (numRead == -1) break;
  total.append(buffer, numRead);
}
空袭的梦i 2024-10-19 04:18:44

我期望 read 的行为
阻塞直到流关闭或
已达到 EOF。

然后你需要检查Javadocs。 read() 的约定是它将至少读取一个字节,必要时会阻塞,直到读完为止,或者直到 EOS 或发生异常。规范中没有任何内容表明它将读取您请求的整个长度。这就是它返回长度的原因。

I would expect the behavior of read to
block until the stream is closed or
EOF is reached.

Then you need to check the Javadocs. The contract of read() is that it will read at least one byte, blocking if necessary until it has done so, or until EOS or an exception occurs. There is nothing in the specification that says it will read the entire length you requested. That's why it returns a length.

十六岁半 2024-10-19 04:18:44

有没有一种方法可以从套接字读取字节,并且始终确保读取 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);

Is there a way of reading bytes from a socket that will always ensure that you read len bytes?

You can use Apache Commons IOUtils, they have a method that does exactly what you need:

    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);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文