Search code examples
c++filememory-managementc++11deque

Storing, retrieving binary data or bytes to and from a file for a std::deque?


I am writing a "replay system" for a game and I'm wondering how I should store the recorded frames?

As for now I have this code / structures (note: this code is shortened):

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

What I was thinking of is, making a raw array of bytes, allocate it to the size of the deque container, copy them with memcpy from the deque to the array and then write all the array bytes to the file..

Then if I would like to read my recording data I would just read the bytes of the file and assign them to a new array, and use memcpy to copy the array contents to a deque..

and this is much like.. well.. the C way? There has to be some other way to do this, store the data in a file , then read it back into the deque (maybe using some C++11 features?).

How would I accomplish this?

Which approach do you recommend?

I am using windows if that matters.


Solution

  • If I interpret your question correctly (I'm tired so please just leave a comment if I'm wrong), you want to write and read your recording to and from file.

    This can easily be done with any struct:

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

    You can test this with

    #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";
    }
    

    For further information about std::basic_ostream::write and std::basic::istream::read, I recommend having a look at cppreference.com