Davinish
Davinish

Reputation: 305

FlatBuffers: Write to and read from binary file?

I have basic knowledge of file streams in C++ and Google FlatBuffers. The Schema file is quite simple, also creating a buffer and reading from a buffer pointer. The thing that I don't get is how to save multiple buffers into a binary file, and then read that binary file to get any random buffer.

Here is a simple Schema with two arrays of floats:

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

.

A function for building the buffer (although without the file saving):

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"?
}

.

And a function for reading the buffer after it was read from the binary file (without the file reading):

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);
    }
}

Not sure if the way to access the buffer's info is correct. For instance the way to get the length of the array fields.

Code examples for file interaction (write/read multiple buffers in one file) would be welcome.

Upvotes: 11

Views: 11855

Answers (4)

Harsh Shah
Harsh Shah

Reputation: 307

Quick reference to store buffer into binary file.

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();

To read from file:

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>());

Upvotes: 3

user5814611
user5814611

Reputation: 61

My solution is adding additional size information.

for writer ::

for (item : flatbuffer_list) {
   int size = item.GetSize();
   write (file, &size, sizeof(size));
   write (file, item.GetBufferPointer(), item.GetSize());
}

for reader ::

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

Upvotes: 3

lezo
lezo

Reputation: 1

"Code examples for file interaction (write/read multiple buffers in one file) would be welcome."

I use fbs and json like this for my test game. (generate to out_cpp folder : gamedata.bin, gamedata.h)

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

and I found this flatbuffers sample which is quite useful at first time.

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

In my case, the git sample is not working correctly unless you use flatbuffers::LoadFile() instead of the sample provided load_file().

Upvotes: 0

Aardappel
Aardappel

Reputation: 6074

The best way to do this to add that list of cars to your schema:

table Garage {
  cars:[Car];
}

Then you can collect multiple car offsets (from CreateCar), call CreateVector on them, call CreateGarage on that, and then feed the result of that to Finish.

To read, start similarly from GetGarage(buffer_pointer).

Upvotes: 3

Related Questions