FlatBuffers:如何写入和读取二进制文件?

11

我对 C++ 中的文件流和 Google FlatBuffers 有基础知识。模式文件很简单,还可以创建缓冲区并从缓冲区指针中读取。 我不明白的是如何将多个缓冲区保存到二进制文件中,然后读取该二进制文件以获取任意缓冲区。

这里是一个带有两个浮点数组的简单模式:

table Car {
    field_a:[float];
    field_b:[float];
}

一个构建缓冲区的函数(尽管没有文件保存功能):

bool save_flatbuf(string file_path, vector<double> vec_a, vector<double> vec_b) {
    flatbuffers::FlatBufferBuilder builder;

    auto vec_floats_a = builder.CreateVector(vec_a, vec_a.size());
    auto vec_floats_b = builder.CreateVector(vec_b, vec_b.size());

    auto mloc = CreateCar(builder, &vec_floats_a, &vec_floats_b);

    builder.Finish(mloc);

    // How to save it into a binary file with a list of "Cars"?
}

并提供一个函数,用于在从二进制文件读取缓冲区后进行读取(无需再次读取文件):

bool read_flatbuf(string file_path) {

    // How to get the buffer pointer to a "Car" from a binary file with a "list of Cars" ? .

    vector<double> final_vec_a;
    vector<double> final_vec_b;

    auto car = GetCar(buffer_pointer);

    auto fa = car->field_a();
    auto fb = car->field_b();

    final_vec_a.resize(fa->size());
    for (int i = 0; i < fa->size(); i++) {
        final_vec_a[i] = fa->Get(i);
    }

    final_vec_b.resize(fb->size());
    for (int i = 0; i < fb->size(); i++) {
        final_vec_b[i] = fb->Get(i);
    }
}

不确定访问缓冲区信息的方式是否正确,例如获取数组字段长度的方式。

欢迎提供文件交互的代码示例(在一个文件中写入/读取多个缓冲区)。


3
+1 我在文档中找不到关于这个的任何内容。(FlatBufferBuilder没有API参考文档,这让我很烦恼。) - masonk
4个回答

3
我的解决方案是添加额外的尺寸信息。
对于写手:
for (item : flatbuffer_list) {
   int size = item.GetSize();
   write (file, &size, sizeof(size));
   write (file, item.GetBufferPointer(), item.GetSize());
}

读者:

while(!eof(file)) {
   int size;
   read (file, &size, sizeof(size));
   read (file, buffer, size);
   auto item = GetItem(buffer);
}

3
最好的方法是将车辆列表添加到您的模式中:
table Garage {
  cars:[Car];
}

然后,您可以收集多个汽车偏移量(从CreateCar),在它们上面调用CreateVector,在其中调用CreateGarage,然后将其结果提供给Finish

要阅读,请从GetGarage(buffer_pointer)开始类似地进行。


当处理大型fbs模式时,这并不方便。比如说你有一个图形,需要循环获取每个操作,然后获取操作的属性,我们需要从缓冲区创建吗? - Nicholas Jela

3

将存储缓冲区快速参考到二进制文件中。

builder.Finish(mloc);
uint8_t *buf = builder.GetBufferPointer();
int size = builder.GetSize();

std::ofstream ofile("data.bin", std::ios::binary);
ofile.write((char *)buf, size);
ofile.close();

从文件中读取:

const std::string inputFile = "data.bin";
std::ifstream infile(inputFile, std::ios_base::binary);
std::vector<char> buffer( std::istreambuf_iterator<char>(infile),
                      std::istreambuf_iterator<char>());

在读取文件时,infile 的声明是什么? - senior_mle

0
欢迎提供文件交互(在一个文件中写入/读取多个缓冲区)的代码示例。
我在我的测试游戏中使用fbs和json,像这样生成到out_cpp文件夹:gamedata.bin,gamedata.h。

flatc -b -c -o out_cpp gamedata.fbs gamedata.json

我发现这个flatbuffers示例非常有用。

https://github.com/gene-hightower/fb

在我的情况下,除非你使用flatbuffers::LoadFile()而不是提供的load_file()示例,否则git示例无法正常工作。

1
仓库链接已损坏。 - user187676

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接