qq jcestruct 结构 python 解析

jcestruct就是类似于protobuff的序列化结构,qq主要就是使用的这个序列化结构,网上的资料比较少,都是Java的,我就写个python的解析吧。

格式内容:

ttlv结构,即tag,type,length,value三个内容。

jcestruct的结构都是一个head,接一个内容。

head结构

通常head为一个字节,既包含type,还包含一个tag表示序号。

一个head的低四位即为type类型,高四位位tag,若tag等于0xf,则head包含两个字节,第二个字节为tag值。

获取head的代码如下:

def readHead():
    head = jcestruct.read(1)
    headdata = struct.unpack('b',head)
    for i in headdata:
        #print(i)
        print("headData:",end='')
        print(hex(i))
        headtag = ((i)& 0xF0)>>4
        headtype = i&0xF
        if 0xF == headtag:
            headtag = jcestruct.read(1)
        print("headtap:",end='')
        print(headtag)
        print("headtype:",end='')
        print(headtype)
    return headtag,headtype

type的格式列表如下:

类型
0byte 或 bool
1Short
2Int
3Long
4Float
5Double
6,7String   6字符串比较短,1个字节代表长度,7字符串比较长,1个int表示长度
8Map  后面第一个int表示长度
9List
10STRUCT_BEGIN 继承了JceStruct类的开始
11STRUCT_END 继承了JceStruct类的结束
12ZERO_TAG
13TYPE_SIMPLE_LIST 后来加的一个结构,就是个bytes数组,不知道为什么要有这个结构,先接一个byte表示长度类型,

 

# -*- coding: utf-8 -*-
"""
Created on Fri Feb  7 16:49:39 2020

@author: lth
"""
import struct

TYPE_BYTE = 0;
TYPE_SHORT = 1
TYPE_INT = 2
TYPE_LONG = 3
TYPE_FLOAT = 4
TYPE_DOUBLE = 5
TYPE_STRING1 = 6
TYPE_STRING4 = 7
TYPE_MAP = 8
TYPE_LIST = 9
#子结构  0A*******0B
TYPE_STRUCT_BEGIN = 10
TYPE_STRUCT_END = 11
TYPE_ZERO_TAG = 12
TYPE_SIMPLE_LIST = 13





def readHead():
    head = jcestruct.read(1)
    if b'' == head:
        print('complete!')
        return 0,12
    print(head)
    headdata = struct.unpack('b',head)
    for i in headdata:
        headtag = ((i)& 0xF0)>>4
        headtype = i&0xF
        if 0xF == headtag:
            headtag = jcestruct.read(1)
        '''
        print("headData:",end='')
        print(hex(i))
        print("headtap:",end='')
        print(headtag)
        print("headtype:",end='')
        print(headtype)
        '''
    return headtag,headtype
    


    
def switchType(typ):
    if TYPE_BYTE == typ:
        print("tag:byte")
        jceData = jcestruct.read(1)
        print(int.from_bytes(jceData,'little'))
        return int.from_bytes(jceData,'little')
        
    elif TYPE_SHORT == typ:   ##short
        print("tag:short")
        jceData = jcestruct.read(2)
        print(jceData)
    elif TYPE_INT == typ:  ##int
        print("tag:int")
        jceData = jcestruct.read(4)
        print(jceData)
    elif TYPE_LONG == typ:  ##long
        print("tag:long")
        jceData = jcestruct.read(8)
        print(jceData)
    elif TYPE_FLOAT == typ:    ##float
        print("tag:float")
        jceData = jcestruct.read(8)
        print(jceData)
    elif TYPE_DOUBLE == typ:   ###double
        print("tag:double")
        jceData = jcestruct.read(8)
        print(jceData)
    elif TYPE_STRING1 == typ:  ##sting
        print("tag:string")
        jceDatalen = jcestruct.read(1)
        
        jceDatalen = int().from_bytes(jceDatalen,byteorder='big', signed=False)
        #print(int().from_bytes(jceDatalen,byteorder='little', signed=False))
        
        jceData = jcestruct.read(jceDatalen)
        print(jceData)
    elif TYPE_STRING4 == typ:  ##long string
        print("tag:long")
        jceDatalen = jcestruct.read(4)
        
        jceData = jcestruct.read(int(jceDatalen))
        print(jceData)
    elif TYPE_MAP == typ:  ##map
        print("tag:map",end='')
        jceDatalen = jcestruct.read(2)    ##取map个数格式
        jceDatalen = int.from_bytes(jceDatalen,'big')
        print(jceDatalen)
        print('[')
        for i in range(0,jceDatalen):
            a,b = readHead()
            print("key is:",end='')
            switchType(b)
            a,b = readHead()
            print("value is:",end='')
            switchType(b)
        
    elif TYPE_LIST == typ:   ##list
        print("tag:list")
        jceDatalen = jcestruct.read(2)    ##取map个数格式
        jceDatalen = int.from_bytes(jceDatalen,'big')
        print(jceDatalen)
        for i in range(0,jceDatalen):
            tag,typ = readHead()
            switchType(typ)
        jceData = jcestruct.read(jceDatalen)
        print(jceData)
    elif TYPE_STRUCT_BEGIN == typ:   ##0a  begin 0b end
        print("tag:begin")
        tag,typ = readHead()
        #print(typ)
        switchType(typ)
#        print(jceData)
    elif TYPE_STRUCT_END == typ:
        print("tag:end")
        jceData = jcestruct.read(1)
        print(jceData)
    elif TYPE_ZERO_TAG == typ:   ##zero
        print("tag:deadline")
        return
    elif TYPE_SIMPLE_LIST == typ: ##simple list
        jcestruct.read(1)
        tag,typ = readHead()
        if typ == TYPE_SHORT:
            jceDatalen = jcestruct.read(2)
            jceDatalen = int().from_bytes(jceDatalen,byteorder='big', signed=False)
            jceData = jcestruct.read(jceDatalen)
            print(jceData)
        elif typ == TYPE_BYTE:
            jceDatalen = jcestruct.read(1)
            jceDatalen = int().from_bytes(jceDatalen,byteorder='big', signed=False)
            jceData = jcestruct.read(jceDatalen)
            print(jceData)
            
    
#print(headtag)
if __name__ == '__main__':
    jcestruct = open('test.bin','rb') #output
    tag1,type1 = readHead()
    while(TYPE_ZERO_TAG != type1):    
        switchType(type1)
        tag1,type1 = readHead()
    jcestruct.close()

 

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值