Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java DataInputStream.read返回的长度小于len_Java_Sockets_Inputstream_Datainputstream - Fatal编程技术网

Java DataInputStream.read返回的长度小于len

Java DataInputStream.read返回的长度小于len,java,sockets,inputstream,datainputstream,Java,Sockets,Inputstream,Datainputstream,我正在使用DataInputStream从套接字读取一些字节。我有一个从流中读取的预期字节数(在解码一个报头后,我知道消息中有多少字节),它99%的时间工作,但偶尔我会让读取的字节数小于len 是什么导致numRead小于len?不是-1。我希望在流关闭或达到EOF之前,读取行为都会被阻塞,但是如果它是流下面的套接字,除非套接字关闭,否则不应该发生这种情况,对吗 是否有一种从套接字读取字节的方法可以确保您始终读取len字节 谢谢编辑:对于一般的流,您只需继续阅读,直到您基本上已经阅读了所有您想要

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

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

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


谢谢编辑:对于一般的流,您只需继续阅读,直到您基本上已经阅读了所有您想要的内容。对于
DataInput
(例如
DataInputStream
)的实现,您应该像Peter Lawrey建议的那样,使用
。考虑剩下的这个答案和一般情况下的情况有关,你只有一个<代码>输入流< /代码>。

任何类型的
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;
}
byte[]data=新字节[messageSize];
int totalRead=0;
while(totalRead
read每次都返回当时可用的位,完成时返回-1,这通常是您应该执行的操作

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

您可以这样使用DataInputStream

byte[] bytes = new byte[len];
dis.readFully(bytes);
这将返回所有读取的数据或引发IOException

我希望read的行为 阻塞,直到流关闭或关闭 达到EOF

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

是否有一种从套接字读取字节的方法可以确保您始终读取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);

ByteArrayInputStream
如果到达其末尾,读取的数据仍将少于请求的数据。@Stephen:没错,但如果您完全知道那里有更多的数据,那么我会非常惊讶地看到它返回的数据更少。我会编辑来澄清的。很好的解释了发生了什么。然而,我认为Peter Lawrey关于Readfull的建议比使用while循环来读取全部数据更干净。@Dunes:在DataInputStream的情况下,你完全正确:)我没有注意到这一点。对于非DataInput,使用循环版本非常有用。将编辑。是的,len在这里可以是常数,例如1024
    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);