Jump to content
  • Advertisement

Archived

This topic is now archived and is closed to further replies.

Genjix

Classes reading/writing to files

This topic is 5127 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

I am currently trying to save a class to a binary file
#include <stdio.h>
#include <stdlib.h>

#include <iostream>
#include <fstream>
......

int main()
{
	/*The choice to read or write, 0 writes and 1 reads*/
	short cho = 0;
	std::cin >> cho;

	Init();

	/*Writing block*/
	if( (cho == 0) || (cho == 3) )
	{
			Statspr    gas( "data/pic/gas.bmp" , "data/pic/gas.bmp" , "data/pic/gasc.bmp" );
			gas.x = 300;		gas.y = 200;

			Array array;
			array.Push( gas );

			gas.x = 500;
			array.Push( gas );

 		std::ofstream ofile;
 		ofile.open("shit", std::ios::binary );
 		ofile.write((char *) &array , sizeof array);
 		ofile.close();
	}

	/*Reading block*/
	if( (cho == 1) || (cho == 3) )
	{
			Array sheet;

 		std::ifstream ifile;
 		ifile.open("shit" , std::ios::binary );
 		ifile.read((char*) &sheet , sizeof sheet);
 		ifile.close();

		/*Draw the sprite to the screen*/
 		sheet.Rad(0)->Draw();	SDL_Flip(screen);	SDL_Delay(4000);
	}



	/*What was your choice*/
	pr "\ncho is " << cho << ''\n'';

	SDL_Quit();
	exit(1);
	return 0;
}
 
as such, choosing to write then read (entering 3) will display the picture but saving in one run(0), then in the second run reading(1) will not display anything. I have tried something like
			Array sheet;
			char *adress = &sheet;

 		std::ifstream ifile;
 		ifile.open("shit" , std::ios::binary );


		while(ifile.get(*adress))
		{	adress++;		}
 
but of course there is no way to make a char pointer point to a class... Is there anyway I could write a whole class to a binary file using one app, and read it using a second app? Also how can I reference a pointer of one type to another?

Share this post


Link to post
Share on other sites
Advertisement
Remember that saving a pointer doesn't save what it points to.

but of course there is no way to make a char pointer point to a class...

Yes, there is : (char*) &object

Is there anyway I could write a whole class to a binary file using one app, and read it using a second app?

Yes. Watch out for those pointers in the class though. If it does contain any, you've got to save it one member at a time.

Also how can I reference a pointer of one type to another?

A cast?

[edited by - Fruny on May 8, 2004 7:56:56 AM]

Share this post


Link to post
Share on other sites
A class containing dynamically allocated memory cannot be written to disc directly and be restored correctly later. You can make a char* point to anything, but that is not your solution. You need to overload operators >> and << to properly read and write your class. Then the write code is no more then ''myfstream << myclass'', and the read is, similarily, ''myfstream >> myclass''.

The string literals in your sprite constructor suggest that you are using std::string, which contains dynamic memory. The usage of your Array class also suggest it contains dynamic memory.

Chances are, writing that Array to disc is only writing a pointer. Loop through the elements and write them all seperatly.

Share this post


Link to post
Share on other sites
First of all, I don't think this is a serious issue, but you should use the combination of flags std::ios::binary | std::ios::out for writing a binary file, and the combination of flags std::ios::binary | std::ios::in for reading a binary file. I think it still works with just the std::ios::binary flag, but it's not good practice to do that.

Anyways, you need what's called serialization - turning a class into raw data and back again. You should give your class to public methods called Serialize and Deserialize. For example:
class MyClass
{
public:
void Serialize(std::ostream & out); // Serialize this object to the ostream out

void Deserialize(std::istream & in); // Deserialize from istream in into this object

...
private:
int anInt;
double aDouble;
char aCstring[64];
SomeObject anObject;
SomeObject *aPointer;
};

void MyClass::Serialize(std::ostream & out)
{
out.write((char *)&anInt, sizeof(int));
out.write((char *)&aDouble, sizeof(double);
out.write(aCstring, 64 * sizeof(char));

anObject.Serialize(out); // Call anObject's Serialize function recursively


char zero = 0, one = 1;

if(aPointer)
{
out.write(&one, sizeof(char)); // Write a flag if aPointer is NULL or not

aPointer->Serialize(out);
}
else
out.write(&zero, sizeof(char));
}

void MyClass::Deserialize(std::istream & in)
{
in.read((char *)&anInt, sizeof(int));
in.read((char *)&aDouble, sizeof(double)0;
in.read(aCstring, 64 * sizeof(char));

anObject.Deserialize(in); // Deserialize anObject recursively


char flag;

in.read(&flag, sizeof(char));

if(flag)
{
aPointer = new SomeObject; // Or find a way to get the address of an existing SomeObject object

aPointer->Deserialize(in);
}
}


Then, to read/write the data, you just do something like:

int i;

int size = array.size();
ofile.write((char *)&size, sizeof(int)); // Write size, otherwise we don't know how big the array is when reading it in


for(i = 0; i < array.size(); i++) // Or, if you want, you can use std::for_each, but then you'll need to change the Serialize/Deserialize functions into functors

array[i].Serialize(ofile);

...

int size;
ifile.read((char *)&size, sizeof(int)); // Read size back in

array.resize(size);

for(i = 0; i < size; i++)
array[i].Deserialize(ifile);


Hope this helps.

[edited by - aprosenf on May 8, 2004 11:50:58 AM]

Share this post


Link to post
Share on other sites
Ok thank you very much, i was hoping it was possible , makes sense now if only an adress is being stored (bit long for a binary file but still, probably a list of adresses).
I wrote the classes scripted (i.e Push( params... )) so all I really need to do is sort out some sort of text scripting.

Thanks very much.

Share this post


Link to post
Share on other sites

  • Advertisement
×

Important Information

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

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!