关于java:从InputStream解码字节

Decoding bytes from InputStream

如果我有一个用以下格式编码的字节流:

1
2
3
4
5
6
0x20 Length D_1 D_2 ... D_n CS

0x20...marks the beginning of a data frame
Length...number of bytes following
D_1-D_n...data bytes (interpreted as signed ints)
CS...One Byte Checksum

例子:

1
2
3
4
0x20 0x05 0x01 0x02 0xD1 0xA1 0xAF
0x20 0x05 0x12 0x03 0x02 0x3A 0xF2
...
...

我如何以一种常见且高效的方式从输入流解码这个字节流?我的想法是使用BufferedInputStream和以下过程(伪代码):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
BufferedInputStream bufIS = new BufferedInputStream(mInStream);
while (true ) {
    byte startFrame = bufIS.read();

    if(startFrame == 0x20) { //first byte must mark the beginning of a data frame
        int length = bufIS.read();
        byte dataframe[] = new bye[length];
        for (int i = 0; i<length i++) { //read data bytes
            dateframe[i] = bufIS.read();
        }

    if(verifyChecksum(bufIS.read()) postEvent(dataframe);
    }
}

这是从输入流接收数据帧的适当方法吗?我想不出更好的解决办法。还有一种可选的read(byte[] b, int off, int len)方法,它从流中读取大量字节,但不能保证读取len个字节,因此我认为这在我的情况下没有帮助。


ID使用带有自定义反序列化的objectinputstream。

因此,编写一个类,它有一个int列表,并实现readObject,这样当给定一个inputstream时,它会读取常量(并丢弃它),然后读取长度,然后输入n,然后校验和,并可选地验证它。

这将所有代码保持在一个位置,并允许您从数据流中读取完全形成的对象。


我在某个阶段完成了二进制序列化的工作,我们在read()方法中使用了bufferedInputstream。更重要的是,由于我们使用的是网络流端,"len"几乎总是不受欢迎的。

相反,我们所做的是编写自己的helper方法,使用一个长度和缓冲区作为参数,然后返回那些字节,以便解码使用我们需要的。只有当我们确信将获得流中字节的完整长度时(以及只要它是我们读取的有效流),我们才使用它。