Хранение, извлечение двоичных данных или байтов в и из файла для std :: deque?

Я пишу «систему воспроизведения» для игры, и мне интересно, как мне хранить записанные кадры?

На данный момент у меня есть этот код / ​​структуры (примечание: этот код сокращен):

struct Point4D { float x, y, z, w; };
struct Point3D { float x, y, z; };
struct Point2D { float x, y; };
struct QuatRot { Point4D Front,Right,Up; };
struct VehicleInfo
{
Point3D     Pos,Velocity,TurnSpeed;
QuatRot     Rotation;
};
namespace Recorder
{
struct FrameInfo
//~380 bytes / frame| max 45600 bytes @ 120 fps
//max 3.7 GB raw data for 24 hours of recording, not bad..
{
std::chrono::high_resolution_clock::duration time;
VehicleInfo Vehicle;
int Nitro;
float RPM;
int CurrentGear;
};

std::deque<FrameInfo> frames;
FrameInfo g_Temp;

void ProcessRecord()
{
//record vehicle data here to g_Temp
frames.push_back(g_Temp);
return;
}
//other recording code.......
};

Я думал о том, чтобы создать необработанный массив байтов, распределить его по размеру контейнера deque, скопировать их с помощью memcpy из deque в массив и затем записать все байты массива в файл.

Затем, если я хотел бы прочитать мои данные записи, я бы просто прочитал байты файла и назначил их новому массиву, и использовал memcpy для копирования содержимого массива в deque ..

и это очень похоже на … ну .. С-путь?
Должен быть какой-то другой способ сделать это, сохранить данные в файле, а затем прочитать их обратно в deque (возможно, с использованием некоторых функций C ++ 11?).

Как бы я это сделал?

Какой подход вы рекомендуете?

Я использую окна, если это имеет значение.

0

Решение

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

Это легко сделать с любой структурой:

struct Foo
{
float bar;
int baz;
};
std::ostream& operator<<(std::ostream& stream, const Foo &foo)
{
stream << foo.bar << " " << foo.baz;
}
std::ofstream& operator<<(std::ofstream& stream, Foo &foo)
{
stream.write(reinterpret_cast<char*>(&foo.bar), sizeof(bar));
stream.write(reinterpret_cast<char*>(&foo.baz), sizeof(baz));
}
std::ifstream& operator>>(std::ifstream& stream, Foo &foo)
{
stream.read(reinterpret_cast<char*>(&foo.bar), sizeof(bar));
stream.read(reinterpret_cast<char*>(&foo.baz), sizeof(baz));
}

Вы можете проверить это с

#include <fstream>
#include <iostream>

int main()
{
Foo foo;
foo.bar = -1.2f;
foo.baz = 37;
std::cout << foo << "\n";
std::ofstream output;
output.open("myfile", std::ios::binary);
output << foo;
output.close();
std::ifstream input;
input.open("myfile", std::ios::binary);
input >> foo;
input.close();
std::cout << foo << "\n";
}

Для получения дополнительной информации о std::basic_ostream::write а также std::basic::istream::read, Я рекомендую взглянуть на cppreference.com

0

Другие решения

memcpy это преждевременная оптимизация.

При чтении содержимого с диска узким местом является дисковый ввод-вывод, а не копирование его из одной части памяти в другую.

Исправьте структуру данных, чтобы она использовала структуры данных фиксированного размера (вместо int, используйте 32-битный int и т. д.).

Не пиши std::chrono::high_resolution_clock::duration в двоичном — обновление библиотеки могло бы полностью изменить размер, без того чтобы они не моргали и не проливали слезу, не говоря уже о его значении. Написать в ms или что-то еще, поэтому значение всегда остается неизменным в (скажем) 64-битном целом числе. Затем вы можете прочитать его обратно в свой std::chrono::high_resolution_clock::duration,

При сериализации всегда записывайте номер версии и размер структуры, чтобы десериализация могла обрабатывать даже элементарные версии.

Я написал бы «в поток» и «из потока». «Поток» выпиши номер версии и размер. «from stream» считывает номер и размер версии, загружает каждое поле как текущей версии, так и версии потока, очищает оставшиеся, а затем считывает оставшиеся данные из потока.

Если вы обнаружите, что вам нужно больше производительности, вы заметите, что положение и угол наклона вашего автомобиля будут меняться гораздо чаще, чем шестерни. Кроме того, удаление фреймов, которые разумно интерполируются между существующими фреймами, значительно уменьшит размер вашего формата воспроизведения (это не так, как если бы вы выполняли физику в воспроизведении, учитывая ваше описание). Наконец, если у вас есть согласованная физическая модель, возможно сохранение только пользовательского ввода и повторного воспроизведения на основе этого (но это трудно осуществить).

Другие маразмы: SRECORDASSIGN можно заменить, просто позвонив operator= на рассматриваемых структурах. Магические числа как 0x4C применять к указателям глупо и почти всегда заменяется простым доступом к элементу структуры.

1

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector