小编典典

java BufferedReader的特定长度返回NUL个字符

java

我有一个TCP套接字客户端,它从服务器接收消息(数据)。消息的类型为长度(2个字节)+数据(长度字节),由STX和ETX字符分隔。

我正在使用bufferedReader来检索前两个字节,对长度进行解码,然后再次从同一bufferedReader中读取适当的长度,并将结果放入char数组中。

在大多数情况下,我都没问题,但是有时(收到的数千条消息中有1条),当尝试从读取器读取(长度)字节时,我只得到其中的一部分,其余的数组都用“
NUL”字符。我想这是因为缓冲区尚未填充。

char[] bufLen = new char[2];
_bufferedReader.read(bufLen);

int len = decodeLength(bufLen);

char[] _rawMsg = new char[len];
_bufferedReader.read(_rawMsg);

return _rawMsg;

我以几种迭代的方式解决了这个问题:

  • 首先,我测试了数组的最后一个字符:如果不是ETX,我将一个一个地从bufferedReader读取字符,直到到达ETX,然后从常规例程开始。结果是我基本上会丢弃一条消息。

  • 然后,为了仍然检索该消息,我将在我的“截断”消息中找到NUL字符的第一次出现,一次读取并存储其他字符,直到到达ETX,然后将它们附加到我的“截断”消息中,确认长度可以。

它也可以工作,但是我真的在想我可以做得更好,例如在读取缓冲区之前检查缓冲区中是否有我需要的字符总数,但是找不到正确的方法…

有什么想法/指针吗?

谢谢 !


阅读 413

收藏
2020-11-30

共1个答案

小编典典

InputStream读取方法可能返回短读取;您必须检查返回值以确定已读取的字符数,并继续循环读取直到获得所需的数字。该方法可能会阻塞,但是只会阻塞直到
某些 数据可用(不一定是您请求的所有数据)可用为止。

大多数人最终都会编写一个“ readFully”方法,例如DataInputStream,该方法读取预期的数据量或引发IOException:

static public int readFully(InputStream inp, byte[] arr, int ofs, int len) throws IOException {
    int                                 rmn,cnt;

    for(rmn=len; rmn>0; ofs+=cnt, rmn-=cnt) {
        if((cnt=inp.read(arr,ofs,rmn))==-1) { 
            throw new IOException("End of stream encountered before reading at least "+len+" bytes from input stream"); 
            }
        }
    return len;
    }
2020-11-30