android对象二进制化,[Android] PacketParser 二进制协议转换工具

这个工具通过自动生成解析类,实现了字节数组和对象之间的转换。

1. 0.40更新

版本0.40发布,更新内容如下所示:

支持继承

支持对象作为字段

支持条件解析字段

支持忽略字段

支持对象List

使用0.40版本,你可以做到:

以TLV格式的数据为例,首先定义一个基类:

@ParsePacket({

"type:1",

"length:2",

"~value:this.length" // ~表示解析该字段但不会移动buffer的cursor

})

public class TLVHeaderObject {

public byte type;

public short length;

public byte[] value;

}

再定义一个普通的TLV类:

@ParsePacket({

"type:1",

"length:2",

"value:this.length"

})

public class TLVObject {

public byte type;

public short length;

public byte[] value;

}

对于任意一个TLV协议单元,可以定义一个类继承TLVHeaderObject:

@ParsePacket({

"tlvObject", // 字段可以是任意以@ParsePacket标注的类,无需指定数据长度

"c:4",

"2a:4", // 字段名前的数字表示该字段出现的次数,包装在List中

"[this.c > 0x02]*b", // “[]”中括号内的为条件解析语句,括号内的表达式为true才会解析该字段。

// 表达式内可通过this引用任意public方法。

// “*b”表示b可出现0次或多次,包装在List中。注意“*”仅可用于最后一个元素

})

public class TLVHolderListObject extends TLVHeaderObject /* 会先解析父类 */ {

public TLVObject tlvObject;

public int c;

public List a;

public List b;

}

留意代码中注释标注出的新特性。

编译项目后,可以通过如下测试:

byte[] bytes = hexToBytes("0a000fBB0003010101000000030000000100000002BB0003010100BB000101BB00020101");

// 使用生成的TLVHolderListObjectPacketParser解析字节数组

TLVHolderListObject tlvHolderListObject = TLVHolderListObjectPacketParser.parse(bytes);

// 检查TLV头部,即继承TLVHeaderObject的部分

assertEquals((byte) 0x0A, tlvHolderListObject.type);

assertEquals(0x000f, tlvHolderListObject.length);

// 检查对象作为字段

assertEquals((byte) 0xBB, tlvHolderListObject.tlvObject.type);

assertEquals(0x0003, tlvHolderListObject.tlvObject.length);

assertArrayEquals(new byte[]{0x01, 0x01, 0x01}, tlvHolderListObject.tlvObject.value);

// 检查普通字段

assertEquals(0x3, tlvHolderListObject.c);

// 检查列表字段

assertEquals(Integer.valueOf(0x1), tlvHolderListObject.a.get(0));

assertEquals(Integer.valueOf(0x2), tlvHolderListObject.a.get(1));

// 依次检查列表对象

assertEquals(3, tlvHolderListObject.b.size());

TLVObject b0 = tlvHolderListObject.b.get(0);

assertEquals((byte) 0xBB, b0.type);

assertEquals(0x0003, b0.length);

assertArrayEquals(new byte[]{0x01, 0x01, 0x00}, b0.value);

TLVObject b1 = tlvHolderListObject.b.get(1);

assertEquals((byte) 0xBB, b1.type);

assertEquals(0x0001, b1.length);

assertArrayEquals(new byte[]{0x01}, b1.value);

TLVObject b2 = tlvHolderListObject.b.get(2);

assertEquals((byte) 0xBB, b2.type);

assertEquals(0x0002, b2.length);

assertArrayEquals(new byte[]{0x01, 0x01}, b2.value);

// 检查对象转字节数组

byte[] toBytes = TLVHolderListObjectPacketParser.toBytes(tlvHolderListObject);

assertArrayEquals(bytes, toBytes);

2. 介绍

2.1. 使用@ParsePacket注解标注实体类

@ParsePacket(

"header:1", // 需要按照解析的顺序写

"cmd:2", // 格式为:[字段名:数据长度]

"len:2", // 数据长度需要与数据类型对应,如例子所示

"seq:2",

"mac:6",

"data:this.len-6", // 可以用“this.fieldname”来引用任意public的属性或方法

"check:1",

"tail:1"

)

public class TargetObject {

public byte header;

public short cmd;

public short len;

public short seq;

public byte[] mac;

public byte[] data;

public byte check;

public byte tail;

}

2.2. 框架自动生成解析类 PacketParser

public class TargetObjectPacketParser {

public static final TargetObject parse(byte[] src) {

return parse(src, new TargetObject());

}

public static final TargetObject parse(byte[] bytes, TargetObject src) {

...

return src;

}

public static final byte[] toBytes(TargetObject src) {

...

return byteBuffer.array();

}

}

注:需Builder一次项目,PacketParser才会生成。

2.3. 使用方法

String data = "AA11220008556677889911223344556677";

byte[] bytes = hexToBytes(data);

// bytes to object

TargetObject targetObject = TargetObjectPacketParser.parse(bytes); // suffix with "PacketParser"

//object to bytes

byte[] toBytes = TargetObjectPacketParser.toBytes(targetObject);

Gradle

buildscript {

repositories {

jcenter()

}

dependencies {

...

classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8' // add this

...

}

}

apply plugin: 'com.android.application'

apply plugin: 'com.neenbedankt.android-apt'

apt 'com.squareup:javapoet:1.8.0'

apt 'com.google.auto:auto-common:0.6'

apt 'com.google.auto.service:auto-service:1.0-rc2'

apt 'com.legendmohe.maven:packetparser-compiler:x.y'

compile 'com.legendmohe.maven:packetparser-annotation:x.y'

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,下面是一个简单的 Qt 程序,用于解析报文。假设我们有一个二进制报文数据,格式为: | 2 bytes | 1 byte | variable length | | -------|-------| -----------------| | Length | Type | Data | 其中 Length 是数据部分的长度,Type 是数据类型,Data 是数据本身。 我们需要解析这个报文,并将结果显示在界面上。下面是代码示例: ```cpp #include <QtWidgets> class PacketParser : public QObject { Q_OBJECT public: PacketParser(QObject *parent = nullptr) : QObject(parent) {} public slots: void parsePacket(const QByteArray &packetData) { // 读取 Length 和 Type QDataStream stream(packetData); quint16 length; quint8 type; stream >> length >> type; // 读取 Data QByteArray data = packetData.mid(sizeof(length) + sizeof(type), length); // 将结果发送给界面 emit packetParsed(QString("Type: %1\nData: %2").arg(type).arg(QString::fromUtf8(data))); } signals: void packetParsed(const QString &parsedData); }; class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(QWidget *parent = nullptr) : QMainWindow(parent) { QLabel *label = new QLabel(tr("Waiting for packet..."), this); setCentralWidget(label); // 创建 PacketParser 对象 m_parser = new PacketParser(this); // 连接信号和槽 connect(m_parser, &PacketParser::packetParsed, label, &QLabel::setText); } protected: void keyPressEvent(QKeyEvent *event) override { if (event->key() == Qt::Key_Space) { // 模拟接收到一个报文 QByteArray packetData; QDataStream stream(&packetData, QIODevice::WriteOnly); stream << (quint16)10 << (quint8)1 << "Hello"; m_parser->parsePacket(packetData); } } private: PacketParser *m_parser; }; int main(int argc, char *argv[]) { QApplication app(argc, argv); MainWindow window; window.show(); return app.exec(); } #include "main.moc" ``` 这个程序中,PacketParser 类用于解析报文,MainWindow 类用于显示解析结果。程序运行后,按下空格键模拟接收到一个报文,解析结果将会显示在界面上。 注意:这个程序只是一个简单的示例,实际情况下需要根据具体的报文格式进行修改。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值