jmbockhorst
jmbockhorst

Reputation: 88

Saving and loading class data stored in a binary file in C++

I am trying to save and load data into a binary file so I can retrieve the contents later. The code I has used to work if each data item was the same size, but with this class data, it doesn't work. I made some adjustments to try to fix this by saving a data size variable as well. This however didn't work either. Here's my class:

class Player
{
public:
    Player();
    Player(int playerID, std::string name, std::string country, int startYear, std::vector<int> rankPerYear);
    ~Player();

    int getRank() { return rank; }

private:
    int playerID;
    std::string name;
    std::string country;
    int rankingPts;
    int rank;
    int startYear;
    std::vector<int> rankPerYear;
    Schedule schedule;
    PlayerStats playerStats;
};

And here are my load and save functions:

void GameData::saveGame(std::string fileName)
{
    std::ofstream file;
    fileName += ".bin";
    file.open(fileName.c_str(), std::ios::binary | std::ios::out);

    size_t tempSize = 0;

    for (int i = 0; i < players.size(); i++) {
        tempSize = sizeof(players[i]);
        file.write((char*)&tempSize, sizeof(size_t));

        file.write((char*)&players[i], tempSize);
    }

}

void GameData::loadGame(std::string fileName)
{
    players.clear();
    fileName += ".bin";
    if (std::ifstream(fileName)) {
        std::ifstream file;
        file.open(fileName.c_str(), std::ios::binary | std::ios::in);
        if (!file.is_open()) {
            std::cout << "Error while opening the file";
        }
        else {
            std::string temp;
            int location = 0;
            size_t tempSize = 0;
            Player player;
            while (std::getline(file, temp)) {
                file.seekg(location, std::ios::beg);
                file.read((char*)&tempSize, sizeof(size_t));
                file.seekg(sizeof(size_t) + location, std::ios::beg);
                file.read((char*)&player, tempSize);
                players.push_back(player);
                location += sizeof(size_t) + tempSize;
            }
        }
    }
    else {
        saveGame(fileName);
    }
}

I am saving the players to a vector of Players. When I try to run this I get the error:

Exception thrown at 0x0F485097 (vcruntime140d.dll) in Ping Pong Manager.exe: 0xC0000005: Access violation reading location 0x081BCE20.

When debugging this I found that it would save some of the data correctly, but would then crash before it finished. So I know it's partially working. I have tried many different things but cannot figure my problem. Thanks for the help.

Upvotes: 1

Views: 823

Answers (1)

Tatsuyuki Ishi
Tatsuyuki Ishi

Reputation: 4031

You cannot serialize STL containers directly since they contains pointers.

The common way is to write the field one-by-one, using specialized methods for things that contains pointers to heap.

Please consider a serialization library, which generates the code for you. Here's a list:

Boost.Serialization

Cap'n'Proto

FlatBuffers

Upvotes: 4

Related Questions