FlatBuffers: запись и чтение из двоичного файла?

У меня есть базовые знания о файловых потоках в 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);
    }
}

Не уверен, что способ доступа к информации о буфере правильный. Например, способ получить длину полей массива.

Приветствуются примеры кода для взаимодействия с файлами (запись/чтение нескольких буферов в один файл).


person Davinish    schedule 06.11.2014    source источник
comment
+1 Я ничего не могу найти об этом в документах. (Нет ссылки на API для FlatBufferBuilder, и это сводит меня с ума.)   -  person masonk    schedule 13.07.2015


Ответы (4)


Лучший способ сделать это, чтобы добавить этот список автомобилей в вашу схему:

table Garage {
  cars:[Car];
}

Затем вы можете собрать несколько смещений автомобилей (из CreateCar), вызвать для них CreateVector, вызвать для них CreateGarage, а затем передать результат этого в Finish.

Для чтения начните аналогично с GetGarage(buffer_pointer).

person Aardappel    schedule 08.11.2014

Мое решение - добавить дополнительную информацию о размере.

для писателя ::

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);
}
person user5814611    schedule 22.03.2016

Краткий справочник по сохранению буфера в двоичный файл.

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>());
person BlueDragon96    schedule 30.01.2019
comment
Что такое объявление для infile при чтении файла? - person Arnab Sanyal; 02.11.2020

«Приветствуются примеры кода для взаимодействия с файлами (запись/чтение нескольких буферов в один файл)».

Я использую fbs и json для своей тестовой игры. (создать в папку out_cpp: gamedata.bin, gamedata.h)

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

и я нашел этот образец плоских буферов, который очень полезен в первый раз.

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

В моем случае пример git работает неправильно, если вы не используете flatbuffers::LoadFile() вместо предоставленного примера load_file().

person lezo    schedule 12.04.2015
comment
Ссылка на репозиторий битая. - person Erik Aigner; 17.11.2017