How to parse/encode binary message formats?

前端 未结 5 1546
天涯浪人
天涯浪人 2021-02-09 05:59

I need to parse and encode to a legacy binary message format in Java. I began by using DataOutputStream to read/write primitive types but the problem I\'m having is that the mes

5条回答
  •  一整个雨季
    2021-02-09 06:25

    There is a builtin byte type in Java, and you can read into byte[] buffers just fine using InputStream#read(byte[]) and write to an OutputStream using OutputStream#write(byte[], int, int), so there's no problem in that.

    Regarding your messages - as you noted correctly, the tiniest bit of information you get at a time is a byte, so you will have to decompose your message format into 8 bit chunks first:

    Let's suppose your message is in a byte[] named data. I also assume little-endianness.

    A uint32 is 32 bits long -> that's four bytes. (Be careful when parsing this in Java, Java integers and longs are signed, you need to handle that. An easy way to avoid trouble would be taking longs for that. data[0] fills bits 31 - 24, data[1] 23 - 16, data[2] bits 15 - 8 and data[3] bits 7 to 0. So you need to shift them appropriately to the left and glue them together with logical OR:

    long uint32 = ((data[0]&0xFF) << 24) | 
                  ((data[1]&0xFF) << 16) | 
                  ((data[2]&0xFF) << 8)  | 
                   (data[3]&0xFF);
    

    Next, there are two single bits. I suppose you have to check whether they are "on" (1) or "off" (0). To do this, you use bit masks and compare your byte with logical AND.

    First bit: ( binary mask | 1 0 0 0 0 0 0 0 | = 128 = 0x80 )

    if ( (data[4] & 0x80 ) == 0x80 ) // on
    

    Second bit: ( binary mask | 0 1 0 0 0 0 0 0 | = 64 = 0x40 )

    if ( (data[4] & 0x40 ) == 0x40 ) // on
    

    To compose the next uint32, you will have to compose bytes over byte boundaries of the underlying data. E.g. for the first byte take the remaining 6 bits of data[4], shift them two to the left (they will be bit 8 to 2 of the uint32) and "add" the first (highest) two of data[5] by shifting them 6 bits to the right (they will take the remaining 1 and 0 slot of the uint32). "Adding" means logically OR'ing:

    byte uint32Byte1 = (byte)( (data[4]&0xFF) << 2 | (data[5]&&0xFF) >> 6);
    

    Building your uint32 is then the same procedure as in the first example. And so on and so forth.

提交回复
热议问题