Java中使用FlatBuffer创建Ipv6结构体向量缺少辅助方法的问题咨询
如何在FlatBuffer 1.11.0的Java实现中创建结构体向量并关联到列表?
问题背景
假设我们有以下FlatBuffer Schema:
struct Ipv6 { b0: byte; b1: byte; b2: byte; b3: byte; b4: byte; b5: byte; b6: byte; b7: byte; b8: byte; b9: byte; b10: byte; b11: byte; b12: byte; b13: byte; b14: byte; b15: byte; } table Ipv6List { entries: [Ipv6]; } root_type Ipv6List;
在使用FlatBuffer 1.11.0生成的Java类时,我发现Ipv6List没有提供创建结构体向量的常规辅助方法(比如addEntries)——查阅文档后得知这是为了避免临时对象、提升性能的设计。虽然找到了Ipv6List#startEntriesVector静态方法,但不知道后续如何将Ipv6结构体添加到向量,以及如何结束关联获取向量偏移。
我尝试的代码片段如下:
FlatBufferBuilder builder = new FlatBufferBuilder(); final byte[] inetAddressBytes = Inet6Address.getByName("2a01:e35:2e7a:490:6193:c54c:f740:f907").getAddress(); int ipv6Offset = Ipv6.createIpv6(builder, inetAddressBytes[0], inetAddressBytes[1], inetAddressBytes[2], inetAddressBytes[3], inetAddressBytes[4], inetAddressBytes[5], inetAddressBytes[6], inetAddressBytes[7], inetAddressBytes[8], inetAddressBytes[9], inetAddressBytes[10], inetAddressBytes[11], inetAddressBytes[12], inetAddressBytes[13], inetAddressBytes[14], inetAddressBytes[15] ); Ipv6List.startEntriesVector(builder, 1); // how to add the IP to the vector ? // how to end the association and get the vector offset ? // int ipsVectorOffset = ?; int ipListOffset = Ipv6List.createIpv6List(builder, ipsVectorOffset); builder.finish(ipListOffset); ByteBuffer byteBuffer = builder.dataBuffer();
请问如何正确创建Ipv6结构体向量并将其与Ipv6List关联?
解决方案
核心原因是FlatBuffer中结构体(struct)和表(table)的处理逻辑不同:结构体是值类型,直接嵌入在缓冲区中,不需要引用偏移,因此生成的代码不会提供addX这类方法。针对结构体向量,你需要按照以下步骤操作:
修正后的完整代码
FlatBufferBuilder builder = new FlatBufferBuilder(); final byte[] inetAddressBytes = Inet6Address.getByName("2a01:e35:2e7a:490:6193:c54c:f740:f907").getAddress(); // 1. 启动Ipv6向量,指定元素数量 Ipv6List.startEntriesVector(builder, 1); // 2. 写入Ipv6结构体(注意:FlatBuffer向量需要逆序写入,单元素时无需调整顺序) Ipv6.writeIpv6(builder, inetAddressBytes[0], inetAddressBytes[1], inetAddressBytes[2], inetAddressBytes[3], inetAddressBytes[4], inetAddressBytes[5], inetAddressBytes[6], inetAddressBytes[7], inetAddressBytes[8], inetAddressBytes[9], inetAddressBytes[10], inetAddressBytes[11], inetAddressBytes[12], inetAddressBytes[13], inetAddressBytes[14], inetAddressBytes[15]); // 3. 结束向量构建,获取向量偏移 int ipsVectorOffset = builder.endVector(); // 4. 创建Ipv6List并关联向量 int ipListOffset = Ipv6List.createIpv6List(builder, ipsVectorOffset); // 5. 完成FlatBuffer构建 builder.finish(ipListOffset); ByteBuffer byteBuffer = builder.dataBuffer();
关键细节解释
- 启动向量:调用
Ipv6List.startEntriesVector(builder, count)告诉FlatBufferBuilder我们要创建一个包含count个Ipv6结构体的向量。 - 逆序写入结构体:FlatBuffer的缓冲区是从后往前构建的,因此向量的元素需要从最后一个到第一个的顺序写入。如果需要添加多个Ipv6元素,比如两个IP,代码应该是:
// 假设有两个IP字节数组:ipBytesA, ipBytesB Ipv6List.startEntriesVector(builder, 2); // 先写第二个元素(最终向量中会排在后面) Ipv6.writeIpv6(builder, ...ipBytesB的字节...); // 再写第一个元素(最终向量中会排在前面) Ipv6.writeIpv6(builder, ...ipBytesA的字节...); int vectorOffset = builder.endVector(); - 结束向量:调用
builder.endVector()完成向量的构建,返回的偏移就是该向量在缓冲区中的位置,后续可以将其传入Ipv6List.createIpv6List来关联列表。 - 区别
createIpv6和writeIpv6:createIpv6是为了在表中引用单个结构体时使用(返回结构体的偏移),而writeIpv6是直接将结构体的字节写入缓冲区,专门用于构建结构体向量。
内容的提问来源于stack exchange,提问作者Laurent
相关产品推荐
相关产品推荐

