首页 > 技术文章 > TLV格式解析

luyilan 2020-10-28 09:51 原文

TLVTLV格式数据是指由TagLengthValue组成的数据。具体说明如下:

    tag标签的属性为bit,由16进制表示,占12个字节长度。例如,0x9F33”为一个占用两个字节 tag标签。而0x95”为一个占用一个字节的tag标签。若tag标签的第一个字节(注:字节排序方向为从左往右数,第一个字节即为最左边的字节。bit排序规则同理。)的后四个bit“1111”,则说明该tag占两个字节,例如0x9F33”;否则占一个字节,例0x95” 

 

 

子域长度(即L本身)的属性也为bit,占13个字节长度。具体编码规则如下: 
           a)  L 字段最左边字节的最左 bit 位(即 bit8)为 0,表示该 L 字段占一个字节,它的后续 7bit 位(即 bit7bit1)表示子域取值的长度,采用二进制数表示子域取值长度的十进制数。例如,某个域取值占 3 个字节,那么其子域取值长度表示为“00000011”。所以,若子域取值的长度在 1127 字节之间,那么该 L 字段本身仅占一个字节。 
           b)  L 字段最左边字节的最左 bit 位(即 bit8)为 1,表示该 L 字段不止占一个字节,那么它到底占几个字节由该最左字节的后续 7 bit 位(即 bit7bit1)的十进制取值表示。例如,若最左字节为 10000010,表示 L 字段除该字节外,后面还有两个字节。其后续字节的十进制
取值表示子域取值的长度。例如,若 L 字段为“1000 0001 1111 1111”,表示该子域取值占255 个字节。所以,若子域取值的长度在 127255 字节之间,那么该 L 字段本身需占两个字节。

 

解析TLV步骤:

1、TLV数据内容十六进制转为byte字节数组 byte[] aBuf

 

2、循环解析TLV结构内容,从第一个开始

 

(1) 解析tag字节长度

  private int getTagBytesCount(byte[] aBuf, int aOffset) {
        //Tag 第一个字节的B1 到 B5 是否都为1 ,如果是,tag为2个字节
        if((aBuf[aOffset] & 0x1F) == 0x1F) { // see subsequent bytes
            int len = 2;
            for(int i=aOffset+1; i<aOffset+10; i++) {
                if( (aBuf[i] & 0x80) != 0x80) {
                    break;
                }
                len++;
            }
            return len;
        } else {
            return 1;
        }
    }

 

 

(2) 解析tag字节内容

  通过 aBuf , 开始下标和tag长度获取tag字节内容

 

(3) 解析length长度

   private int getLengthBytesCount(byte aBuf[], int aOffset) {
        int len = aBuf[aOffset] & 0xff;
        //最左边字节的最左 bit 位(即 bit8)为 1,表示该 L 字段不止占一个字节,
        //字节数由该最左字节的后续 7 个 bit 位(即 bit7~bit1)的十进制取值表示
        if( (len & 0x80) == 0x80) {
            return 1 + (len & 0x7f);
        } else {
            return 1;
        }
    }

 

(4) 解析length字节内容(即value的长度)

 

    private int getDataLength(byte[] aBuf, int aOffset) {

        int length = aBuf[aOffset] & 0xff;

        if((length & 0x80) == 0x80) {
            int numberOfBytes = length & 0x7f;
            if(numberOfBytes>3) {
                throw new IllegalStateException(String.format("At position %d the len is more then 3 [%d]", aOffset, numberOfBytes));
            }

            length = 0;
            for(int i=aOffset+1; i<aOffset+1+numberOfBytes; i++) {
                length = length * 0x100 + (aBuf[i] & 0xff);
            }

        }
        return length;
    }

 

 

 

 

(5) 通过tag字节内容(B6位,0x20)判断数据类型(基本数据类型和结构数据类型)

 

(bytes[0] & 0x20) != 0

 

如果是基本数据类型,通过length长度直接解析value值;

 

如果是结构数据类型,通过(步骤2)解析length长度字节的内容,

 

推荐阅读