2017-03-11 10 views
1

後で内容を取得できるように、データをバイナリファイルに保存して読み込もうとしています。各データ項目が同じサイズであっても、このクラスデータでは機能しない場合、私が使用していたコードです。データサイズ変数を保存することでこれを修正しようとしました。しかしこれはどちらもうまくいかなかった。ここ は私のクラスです:クラスデータをC++でバイナリファイルに保存してロードする

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

そして、ここでは私の負荷であり、機能を保存します。

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

私は選手のベクトルにプレーヤーを保存しています。私はこれを実行しようとすると、私はエラーを取得する:

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

これをデバッグするとき、私はそれが正確にデータの一部を救うことがわかったが、それが終了する前に、その後クラッシュしていました。だから私はそれが部分的に働いていることを知っている 私は多くの異なることを試みましたが、私の問題を理解することはできません。助けてくれてありがとう。

+1

、これらの誤った "バイナリファイルの読み込み/書き込み" の例は、SOにここに流行しているようです。これは少なくとも今でも同じエラーを伴う3番目のものであり、数多くの(おそらくは数千もの)合計の例があります。 'C'コードを書いているか、' C'互換の型を扱っていない限り、これは 'C++'では正しく動作しません。 – PaulMcKenzie

+1

[このテストプログラム](http://ideone.com/Hkcbe4)は、 'Player 'がPODタイプであるかどうかを判断します。 PODタイプではないので、バイナリの読み書きには使用できません。 – PaulMcKenzie

+0

たとえば、これは先にhttp://stackoverflow.com/a/42729331/4581301と書いてあります。これは主に 'std :: string'を扱いますが、' std :: vector'にも触れています。 – user4581301

答えて

4

STLコンテナにポインタが含まれているため、STLコンテナを直接シリアル化することはできません。

一般的な方法は、ヒープへのポインタを含むものに特殊なメソッドを使用して、フィールドを1つずつ書き込む方法です。

コードを生成するシリアライズライブラリを検討してください。ここにリストがあります:何らかの理由で

Boost.Serialization

Cap'n'Proto

FlatBuffers

+0

クラスとサブクラスの現在の構造で使用するのに最適なライブラリはどれですか? Boostは、実際には複雑で多くの異なるクラスで実装するのが難しいようです。 – jmbockhorst

関連する問題