在QML中如何将JS ArrayBuffer用作ListElement存储十六进制数据
QML中高效存储二进制/十六进制数据到ListModel
问题描述
希望存储输入的十六进制数据,出于内存效率考虑,不想将其转换为十六进制转义字符串,但执行以下代码后,data字段看似未存储任何数据且无报错:
Item { ListModel { id: model } Component.onCompleted: { let dummyInputData = "1\x200\x00\x01234567890" let byteArray = str2ab(tmpString) model.append({"timestamp_utc": 1, "data": dummyInputData}); } // Converts string to 8-bit array buffer. This is used for testing purposes function str2ab(str) { var buf = new ArrayBuffer(str.length); var bufView = new Uint8Array(buf); for (var i=0, strLen=str.length; i < strLen; i++) { bufView[i] = str.charCodeAt(i); } return buf; } }
核心问题分析
- 未定义变量:代码中使用了未声明的
tmpString,导致str2ab函数无法执行,且最终存入ListModel的是原始字符串而非处理后的二进制数据。 - 空字符截断:
dummyInputData中的\x00是ASCII空字符,QML字符串基于C++底层实现,遇到空字符会直接截断,导致后续数据丢失,看起来像未存储有效内容。 - ListModel存储限制:直接存储字符串无法保留含空字符的二进制数据,且原生ArrayBuffer无法直接存入ListModel。
正确实现方案
要高效存储二进制/十六进制数据,推荐使用QML的ByteArray(对应C++的QByteArray),它可直接存储含空字符的二进制数据,内存效率高且无需转义。
实现代码
Item { ListModel { id: model } Component.onCompleted: { // 方式1:从十六进制字符串直接转换(推荐,无转义) // 对应原需求的十六进制数据:1 20 00 01 32 33 34 35 36 37 38 39 30 let hexStr = "31200001323334353637383930"; let byteArray = Qt.byteArrayFromHex(hexStr); // 方式2:从字节序列构造(如果已有ArrayBuffer) // let arrayBuffer = new ArrayBuffer(13); // let uint8View = new Uint8Array(arrayBuffer); // uint8View.set([0x31, 0x20, 0x00, 0x01, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30]); // let byteArray = Qt.byteArrayFromRawData(arrayBuffer); // 存入ListModel model.append({ "timestamp_utc": 1, "data": byteArray }); // 验证存储结果 let storedData = model.get(0).data; console.log("存储的字节长度:", storedData.length); for (let i = 0; i < storedData.length; i++) { console.log(`字节 ${i}:0x${storedData.at(i).toString(16).padStart(2, '0')}`); } } }
方案说明
- Qt.byteArrayFromHex:直接将十六进制字符串转换为ByteArray,无需手动转义特殊字符,是处理十六进制输入的最优方式。
- Qt.byteArrayFromRawData:从已有的ArrayBuffer直接转换为ByteArray,零拷贝操作,内存效率极高。
- ByteArray存储特性:支持包含空字符在内的所有二进制数据,存入ListModel后不会被截断,可完整保留原始数据。
内容的提问来源于stack exchange,提问作者Kenn Sebesta
相关产品推荐
相关产品推荐

