2013-11-28 149 views
0

我创建了两个函数来保存和加载一个对象到程序中。ifstream无法读取

保存功能aparently成功保存对象:

void Game::SaveGame() 
{ 
std::string filename = "saves/miner-save-" + currentDate() + ".gem"; 

std::ofstream outfile; 
outfile.open(filename.c_str(), std::ios::binary); 

outfile.write((char *)(&myGame), sizeof(Game)); 

if (outfile.fail()) 
    std::cout << "write failed" << std::endl; 

outfile.close(); 

std::cout << myGame->myMiner->getX(); //debug purposes : prints 25 

} 

的问题似乎是在负载功能,因为从所读取的对象的整数返回的值是不正确。

void Game::LoadGame() 
{ 

    ..some code.. 

    std::string filename = GetLoadFilename(nameID); //works 

    std::ifstream infile; 
    infile.open(filename, std::ios::binary); 

    infile.read((char *)&myGame, sizeof(Game)); 

    if (infile.fail()) 
    { 
     std::cout << "read failed" << std::endl; 
    } 

    std::cout << myGame->myMiner->getX(); //debug purposes : prints -842150451 

    Play(myGame->myMiner->getX(), myGame->myMiner->getY()); 
} 

类游戏:

class Game { 

    Game *myGame; 
    Miner *myMiner; 
    BlockTypes *myBlockTypes; 
    //Block* myBlocks[10000]; 
    Consola *myConsole; 
    Mine *myMine; 
    int linhas, colunas; 
    int _currentStatus; 

    public: 
    ..some functions such as load & save 
}; 

加载时,总是显示 “读取失败” 的消息,什么是错?

+0

没有看到“游戏”的定义,很难说明原因。我会说保存一个'struct'或'class'的二进制图像只有当它是一个没有指针的POD类型时才会工作。即便如此,这并不是最强大的做事方式。 (它通常会跨越平台,例如,在许多情况下,包括32位和64位x86之间,取决于结构的内容。) –

+0

嗯,我已经添加了游戏信息。基本上有更好的方法来保存类文件中的所有数据吗? – xRed

+3

是的,使用'write'和'read'完全不适用于这种结构。 :-)这些指针将无效,并且不会保存指向的数据。你会想查找_serialization的主题._ Boost有一个序列化库,尽管我从来没有使用它。看这里:http://www.boost.org/doc/libs/1_55_0/libs/serialization/doc/index.html 否则,你将不得不写一些自定义的行为结构和存储它,以及一些东西其他自定义,读取您存储的内容并创建/填充新结构。 –

回答

1

使用指针写入结构会写入指针的值,而不是指向对象的值。 你需要看看序列化。序列化是一种将数据结构化到连续非结构化介质(如硬盘驱动器)的方法。即,如何将你的信息结构化为一行位,这样你就可以从同一行位重构你的对象。以前连接的增强库是一个选项,但也有XMLJSONother solutions,你应该检查。

0

一般的方法是使用“infile >> myGame”。在Game类中,定义运算符< <和运算符>>以覆盖为您的Game类自定义的默认值。

这些函数通常对类的每个成员都有一个>>或< <的列表(如果不定义运算符,这是默认值)。但是你需要做出一些决定并为指针类型成员编写一些代码。内存中对象的位置将从运行转移到运行,因此您不能保存并加载指针值。例如,也许在Game ::运营商< <您需要在myMine上调用< <来转储它(深层复制)。但也许Miner是一个指向一个数组的指针,它被单独保存和加载,所以Game :: operator < <保存了一个矿工ID号或者名称字符串,Game运算符>>使用保存的数据查找Miner以获取指针。