You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

TypeScript中创建流式FlatBuffers的标准实现方式是什么

JavaScript/TypeScript 多长度前缀FlatBuffer合并写入实现方案

你之前的操作误区是将多个Monster实例放到同一个Builder实例中一次性完成序列化,这种方式会将所有实例合并为单个FlatBuffer对象,自然只会生成一个总长度前缀。要实现每个Monster带独立长度前缀、且所有数据存储在同一个Uint8Array的需求,可按以下官方API实现:

实现步骤

  • 第一步:预分配目标缓冲区
    先根据待序列化的Monster数量、单个Monster的平均大小,预分配一个足够容纳所有数据的Uint8Array,避免多次内存申请和数组拼接开销。
  • 第二步:复用Builder实例循环序列化
    复用同一个FlatBuffer Builder实例,每完成一个Monster的序列化就将带长度前缀的内容写入预分配的大数组,随后重置Builder即可处理下一个实例,无需重复创建Builder对象。
  • 第三步:自定义流式校验逻辑
    官方flatc暂不支持为JavaScript生成原生校验函数,你可以在读取时先解析每个Monster的长度前缀,校验剩余可读长度是否充足后再执行解析,即可避免非法数据导致的越界错误。

参考代码(TypeScript)

import { Builder, ByteBuffer } from 'flatbuffers';
// 引入flatc生成的Monster类
import { Monster } from './generated/monster';

// 业务参数配置
const MONSTER_COUNT = 100;
// 预估单个带前缀的Monster序列化后大小为200字节,预留30%冗余避免溢出
const PER_MONSTER_MAX_SIZE = 260;
// 预分配总缓冲区
const totalBuffer = new Uint8Array(MONSTER_COUNT * PER_MONSTER_MAX_SIZE);
let writeOffset = 0;

// 复用单个Builder实例,避免重复初始化开销
const builder = new Builder(PER_MONSTER_MAX_SIZE);

for (let i = 0; i < MONSTER_COUNT; i++) {
  // 重置Builder,清除上一次序列化的残留数据
  builder.reset();

  // 正常构建单个Monster实例
  const nameOffset = builder.createString(`Monster_${i}`);
  Monster.startMonster(builder);
  Monster.addName(builder, nameOffset);
  Monster.addHp(builder, 100 + i);
  const monsterOffset = Monster.endMonster(builder);

  // 生成带独立长度前缀的当前Monster缓冲区
  Monster.finishSizePrefixedMonsterBuffer(builder, monsterOffset);

  // 取出当前带前缀的Monster数据视图(无内存复制开销)
  const currentMonsterBuf = builder.asUint8Array();
  // 写入预分配的总缓冲区
  totalBuffer.set(currentMonsterBuf, writeOffset);
  // 更新写入偏移
  writeOffset += currentMonsterBuf.length;
}

// 最终得到的合并缓冲区,所有Monster带独立长度前缀,可直接用于流式传输
const finalBuffer = totalBuffer.slice(0, writeOffset);

流式读取示例

const readBuf = new ByteBuffer(finalBuffer);
while (readBuf.position() < readBuf.capacity()) {
  // 先读取4字节长度前缀
  const monsterSize = readBuf.readUint32(readBuf.position());
  // 自定义校验:判断剩余数据长度是否充足
  if (readBuf.position() + monsterSize + 4 > readBuf.capacity()) {
    throw new Error('数据不完整,等待后续数据传输');
  }
  // 解析单个Monster
  const monster = Monster.getSizePrefixedMonster(readBuf);
  // 业务逻辑处理
  console.log(monster.name(), monster.hp());
}

内容的提问来源于stack exchange,提问作者sleep

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 06:54:03