跳转至

pack- 打包和解包格式串 副本

一、概述

pack 核心库提供二进制数据的打包和解包功能,支持多种数据格式和字节序,适用于协议解析、数据序列化等场景。

二、核心示例

1、核心示例是指:使用本库文件提供的核心 API,开发的基础业务逻辑的演示代码;

2、核心示例的作用是:帮助开发者快速理解如何使用本库,所以核心示例的逻辑都比较简单;

3、更加完整和详细的 demo,请参考 LuatOS 仓库 中的 demo/pack

-- 打包示例:将多个数据类型打包为二进制数据
local data = pack.pack('<hIf', 123, 456789, 3.14)
log.info("pack", "打包后的数据:", data:toHex())

-- 解包示例:从二进制数据中解析出原始值
local pos, short_val, int_val, float_val = pack.unpack(data, '<hIf')
log.info("pack", "解包结果:", short_val, int_val, float_val)

-- 字符串打包示例
local str_data = pack.pack('A8', "LuatOS")
log.info("pack", "字符串打包:", str_data:toHex())

三、常量详解

核心库常量,顾名思义是由合宙 LuatOS 内核固件中定义的、不可重新赋值或修改的固定值,在脚本代码中不需要声明,可直接调用;

每个常量对应的常量取值仅做日志打印时查询使用,不要将这个常量取值用做具体的业务逻辑判断,因为LuatOS内核固件可能会变更每个常量对应的常量取值;

如果用做具体的业务逻辑判断,一旦常量取值发生改变,业务逻辑就会出错;

pack 核心库无常量

pack 核心库支持以下格式符号:

  • '<' 设为小端编码
  • '>' 设为大端编码
  • '=' 大小端遵循本地设置
  • 'z' 空字符串,0 字节
  • 'a' size_t 字符串,前 4 字节表达长度,然后接着是 N 字节的数据
  • 'A' 指定长度字符串, 例如 A8, 代表 8 字节的数据
  • 'f' float, 4 字节
  • 'd' double , 8 字节
  • 'n' Lua number , 32bit 固件 4 字节, 64bit 固件 8 字节
  • 'c' char , 1 字节
  • 'b' byte = unsigned char , 1 字节
  • 'h' short , 2 字节
  • 'H' unsigned short , 2 字节
  • 'i' int , 4 字节
  • 'I' unsigned int , 4 字节
  • 'l' long , 8 字节, 仅 64bit 固件能正确获取
  • 'L' unsigned long , 8 字节, 仅 64bit 固件能正确获取

详细用法请查看 demo

四、函数详解

pack.unpack(string, format, init)

功能

解包字符串。

参数

string

参数含义:需解包的二进制字符串;
数据类型:string
取值范围:任意二进制数据;
是否必选:必须传入此参数;

format

参数含义:格式化符号;
数据类型:string
取值范围:支持大小端和多种数据类型详情参考第三章节中的格式符号;
是否必选:必须传入此参数;

init

参数含义:string参数中解包开始位置
数据类型:number
取值范围:默认值为1
是否必选:可选参数;

返回值

local pos, ... = pack.unpack(string, format, init)

有两个返回值 pos 和...;

pos

含义说明:字符串标记的位置;
数据类型:number
取值范围:当前解包操作结束后的位置;
返回示例:5

...

含义说明:第包返回的0个或者多个返回值一个解包的值;
数据类型:any
取值范围:根据format值,可能有多个返回值;
返回示例:1234567893.14

注意事项

1、format 格式必须与数据实际格式匹配,否则可能解包出错;

2、解包位置超出字符串长度时,返回的值为 nil;

3、大小端设置会影响多字节数据的解析结果;

示例

local data = "\x7B\x00\x15\xCD\x5B\x07\xC3\xF5\x48\x40"
local pos, short_val, int_val, float_val = pack.unpack(data, "<hIf")
log.info("pack.unpack", "解包结果:", short_val, int_val, float_val)
-- 输出:解包结果: 123 456789 3.1400001049042

local _,a = pack.unpack(x,">h") --解包成short (2字节)
-- _ 表示忽略的位置返回值,a 是解包出的short值

pack.pack(format, val1, val2, val3, valn)

功能

打包字符串的值。

参数

format

参数含义:格式化符号;
数据类型:string
取值范围:支持大小端和多种数据类型,详见格式符详解;
是否必选:必须传入此参数;

val1

参数含义:第一个需打包的值;
数据类型:any
取值范围:类型需与format匹配
是否必选:必须传入此参数;

val2

参数含义:第二个需打包的值;
数据类型:any
取值范围:类型需与format匹配
是否必选:可选参数;

val3

参数含义:第三个需打包的值;
数据类型:any
取值范围:类型需与format匹配
是否必选:可选参数;

valn

参数含义:第n个需打包的值
数据类型:any
取值范围:类型需与format匹配
是否必选:可选参数;

返回值

local data = pack.pack(format, val1, val2, val3, valn)

有一个返回值 data;

data

含义说明:包含所有格式化变量的二进制字符串;
数据类型:string
取值范围:可以直接用于传输或存储;
返回示例:"\x7B\x00\x15\xCD\x5B\x07\xC3\xF5\x48\x40"

注意事项

1、打包的值必须与 format 指定的类型兼容;

2、字符串格式'A'需要指定长度,如'A8'表示 8 字节字符串;

3、数值超出目标类型范围时会被截断;

4、大小端设置会影响多字节数据的打包结果;

示例

local data = pack.pack('<hIf', 123, 456789, 3.14)
log.info("pack.pack", "打包结果:", data:toHex())
-- 输出:打包结果: 7B0015CD5B07C3F54840

local crc_data = pack.pack('<H', crypto.crc16("MODBUS", "test data"))
log.info("pack.pack", "CRC打包:", crc_data:toHex())
-- 输出:CRC打包: xxxx (具体值取决于CRC计算结果)

五、产品支持说明

支持 LuatOS 开发的所有产品都支持 pack 核心库。