Jump to content
  • Advertisement
Sign in to follow this  
Dandi8

Reading/Writing to a binary file

This topic is 2951 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hey guys!
I've recently been experimenting with reading and loading binary files. I've written simple tile loading/saving functions which, to my complete and utter amazement, don't work.

The functions are as follows:

void LoadTiles(){
ifstream File("Data/Maps/map.bin", ios::in | ios::binary);
File.read ((char*)&Tiles, sizeof (TileSystem));
File.close();
}

void SaveTiles(){
ofstream File("Data/Maps/map.bin", ios::out | ios::binary);
File.write ((char*)&Tiles, sizeof (TileSystem));
File.close();
}


TileSystem is a class btw. and Tiles is a TileSystem.

Saving results in a 1kb file which may or may not contain my class. Loading *seems* to work but then, apparently, a call to "Tiles.size()" gives me an access violation error.

Gee, programming sure is full of bumpy bumps...
What am I doing wrong?

Thanks in advance :)

Share this post


Link to post
Share on other sites
Advertisement
Whether or not that is the right code depends on what TileSystem looks like. If TileSystem is non-POD then this probably completely wrong.

Share this post


Link to post
Share on other sites
Here is TileSystem:


struct sTile{
int x, y;
int tileFrame;
};

class TileSystem{
public:
vector<sTile> Tiles;
sSprite Tilesheet;

void InitTiles(int TilesX, int TilesY, string TileSrc, int TilesWidth, int TilesHeight);
void DrawTiles(int camX, int camY, int layer0R, int layer0G, int layer0B);
void FreeMem();
};

Share this post


Link to post
Share on other sites
As SiCrane predicted, you're not outputting Plain Ol' Data. Your TileSystem structure is comprised of a vector<> instance and sSprite (don't know what that is - a pointer to a texture?).

The sizeof(TileSystem) is (guess) 20-30 bytes. That's all you're writing out from the address you pass to Write(..). It's not writing out the contents of the vector (just a pointer structure for an initialized vector<>=just some pointers), and it's writing out some pointer value that you probably got by creating a sprite or something.

When you read it back in, you're not creating a new vector, nor are you creating whatever sSprite is.

To write out the contents of the vector, think more in terms of:

for(size_type i=0; i<Tiles.size(); i++) File << Tiles;

Don't know what sSprite is, but if it's a pointer, you may want to output information that will allow you to create it after you read that info back in.

Share this post


Link to post
Share on other sites
As an example, whenever I want to serialize a structure I add two functions that do the heavy work for me:

std::ostream& Engine::Debugger::operator<<(std::ostream& stream, const Callstack& callstack)
{
stream << callstack.m_stack.size();
for(auto i = callstack.m_stack.begin(); i != callstack.m_stack.end(); ++i)
stream << *i;

return stream;
}

std::ostrea& Engine::Debugger::operator>>(std::ostrea& stream, Callstack& callstack)
{
std::size_t n;
stream >> n;
callstack.m_stack.resize(n);
for(std::size_t i = 0; i < n; ++i)
{
int value;
stream >> value;
callstack.m_stack.push_back(value);
}

return stream;
}



Of course, this code will only ever compile if the type of the variable "value" defines an operator as well.

Share this post


Link to post
Share on other sites
sSprite is a struct.

Anyways, I decided to test with this:

void LoadTiles(){
ifstream File("Data/Maps/map.bin", ios::in | ios::binary);

for(int i=0; i<Tiles.Tiles.size(); i++){
File >> (char*)&Tiles.Tiles.tileFrame;
}
File.close();
}

void SaveTiles(){
ofstream File("Data/Maps/map.bin", ios::out | ios::binary);

for(int i=0; i<Tiles.Tiles.size(); i++){
File << (char*)&Tiles.Tiles.tileFrame;
}
File.close();
}



Seems to get me really random results for some reason.
Then I thought, why am I putting a & sign in front of my tiles thingies (I got the method from a tutorial of sorts)? Does that automagically give me a refrence to my variable or is it merely the location of it in the memory which I do not want by any means? Then again, I have no idea how else I'd typecast that into a char.
Please don't beat me with a sledgehammer for my noobtalk.

Share this post


Link to post
Share on other sites
When I faced the issue of saving/loading things, I did not want to waste too much time on non-game related programming so I opted to use a library for this.

I used (and still do) Boost Serialization to serialize data structures and boost/archive/... to archive the data to/from file.

This, to me, seems a decent, reliable, and easy solution, so I thought I'd mention it.

Share this post


Link to post
Share on other sites
Thanks but still, I'd like to learn the proper way before thinking of using external libraries for this :)

Share this post


Link to post
Share on other sites
For your code:

for(int i=0; i<Tiles.Tiles.size(); i++){
File >> (char*)&Tiles.Tiles.tileFrame;

Did you try just:

File >> Tiles.Tiles.tileFrame;

and do similarly for the File output.

I'm not sure why you're typecasting it. Is there a reason for that? tileFrame is just an int, correct?

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!