TLV:TLV格式數據是指由Tag,Length,Value組成的數據。具體說明如下:
tag標簽的屬性為bit,由16進制表示,占1~2個字節長度。例如,“0x9F33”為一個占用兩個字節 的tag標簽。而“0x95”為一個占用一個字節的tag標簽。若tag標簽的第一個字節(注:字節排序方向為從左往右數,第一個字節即為最左邊的字節。bit排序規則同理。)的后四個bit為“1111”,則說明該tag占兩個字節,例如“0x9F33”;否則占一個字節,例“0x95”。
子域長度(即L本身)的屬性也為bit,占1~3個字節長度。具體編碼規則如下:
a) 當 L 字段最左邊字節的最左 bit 位(即 bit8)為 0,表示該 L 字段占一個字節,它的后續 7個 bit 位(即 bit7~bit1)表示子域取值的長度,采用二進制數表示子域取值長度的十進制數。例如,某個域取值占 3 個字節,那么其子域取值長度表示為“00000011”。所以,若子域取值的長度在 1~127 字節之間,那么該 L 字段本身僅占一個字節。
b) 當 L 字段最左邊字節的最左 bit 位(即 bit8)為 1,表示該 L 字段不止占一個字節,那么它到底占幾個字節由該最左字節的后續 7 個 bit 位(即 bit7~bit1)的十進制取值表示。例如,若最左字節為 10000010,表示 L 字段除該字節外,后面還有兩個字節。其后續字節的十進制
取值表示子域取值的長度。例如,若 L 字段為“1000 0001 1111 1111”,表示該子域取值占255 個字節。所以,若子域取值的長度在 127~255 字節之間,那么該 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長度字節的內容,