By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
435,081 Members | 1,885 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 435,081 IT Pros & Developers. It's quick & easy.

Saving a binary file help.

P: n/a
Hi all

I've just started learning about saving files. I got bit of a problem. The
following code gives me an error about incompatible types. (Cannot covert
from class character to char *). I would appreciate it if anyone could
either help me out, or direct me to an online resource site that has
information on saving/loading classes. I have found several tutorials, but
they either do not really help (saving text files) or are too difficult for
me to understand. Thanks
class character
{
public:
character();
character(string charName);
virtual ~character();

string getCharName();

private:
string name;
int age;
};

void saveFile(character* characterFile)
{

ofstream writeFile;

writeFile.open("game.dat", ios::binary);

writeFile.write((char *)characterFile, sizeof(character));

writeFile.close();

}

Jul 19 '05 #1
Share this Question
Share on Google+
7 Replies


P: n/a
G-Factor wrote:
Hi all

I've just started learning about saving files. I got bit of a problem. The
following code gives me an error about incompatible types. (Cannot covert
from class character to char *). I would appreciate it if anyone could
either help me out, or direct me to an online resource site that has
information on saving/loading classes. I have found several tutorials, but
they either do not really help (saving text files) or are too difficult for
me to understand. Thanks
class character
{
public:
character();
character(string charName);
virtual ~character();

string getCharName();

private:
string name;
int age;
};

void saveFile(character* characterFile)
{

ofstream writeFile;

writeFile.open("game.dat", ios::binary);

writeFile.write((char *)characterFile, sizeof(character));
DANGER above ... sizeof(character) returns the size of the character
class NOT THE SIZE OF THE STRING.....

I suggest you add a method

operator const & string () const
{
return name;
}

and then you can

writeFile << * characterFile;


writeFile.close();

}


Jul 19 '05 #2

P: n/a
"Gianni Mariani" <gi*******@mariani.ws> wrote in message
news:3F**************@mariani.ws...
I suggest you add a method
operator const & string () const
{
return name;
}
and then you can
writeFile << * characterFile;


And what about the 'age' field ?
I guess G-Factor wanted to save both 'age' and 'name' field.

Fabio
Jul 19 '05 #3

P: n/a

"Fabio" <fa*************@libero.it> wrote in message
news:be**********@newsreader.mailgate.org...
"Gianni Mariani" <gi*******@mariani.ws> wrote in message
news:3F**************@mariani.ws...
I suggest you add a method
operator const & string () const
{
return name;
}
and then you can
writeFile << * characterFile;


And what about the 'age' field ?
I guess G-Factor wanted to save both 'age' and 'name' field.

Fabio


Yes, I want to save the entire class.
Jul 19 '05 #4

P: n/a
Gianni Mariani wrote:
G-Factor wrote:
Hi all

I've just started learning about saving files. I got bit of a
problem. The following code gives me an error about incompatible
types. (Cannot covert from class character to char *). I would
appreciate it if anyone could either help me out, or direct me to an
online resource site that has information on saving/loading classes.
I have found several tutorials, but they either do not really help
(saving text files) or are too difficult for me to understand. Thanks
class character
{
public:
character();
character(string charName);
virtual ~character();

string getCharName();

private:
string name;
int age;
};

void saveFile(character* characterFile)
{

ofstream writeFile;

writeFile.open("game.dat", ios::binary);

writeFile.write((char *)characterFile, sizeof(character));
DANGER above ... sizeof(character) returns the size of the character
class NOT THE SIZE OF THE STRING.....


Well, that's only part of the problem. It will of course include the
size of the string object, but that object probably contains a pointer
to the actual string data. With that cast, only the pointer itself
would be written to the file, _not_ the data it points to.
If you don't have a good reason to write the data in binary form, don't.
It's quite unportable (You can't write the structure on a PC and read
it on a MAC, and maybe not even on the same PC using a different
compiler), produces lots of problems (e.g. you can't use classes that
contain pointers or virtual member function - wrt the C++ standard, you
might only have a chance with PODs AFAIK) and in many cases isn't worth
it.
I suggest you add a method

operator const & string () const
You probably meant:

operator const string & () const
{
return name;
}

and then you can

writeFile << * characterFile;
What about the age?


writeFile.close();

}


Jul 19 '05 #5

P: n/a

"G-Factor" <ge***@iprimus.com.au> wrote in message
news:3f********@news.iprimus.com.au...
And what about the 'age' field ?
I guess G-Factor wanted to save both 'age' and 'name' field.

Fabio


Yes, I want to save the entire class.

IMHO you can overload the operator << to save object data into file
(serialize) and >> operator to load object data from file (deserialize)
I wrote a simple example without error-checks so please take it as a pure
sample.

class character
{
public:
character() {};
character(std::string charName) : name(charName) {}
virtual ~character() {};

std::string getCharName();

private:
friend std::ostream& operator << (std::ostream& s, const character& c);
friend std::istream& operator >> (std::istream& s, character& c);

std::string name;
int age;
};

std::ostream& operator << (std::ostream& s, const character& c)
{
std::string::size_type stype = c.name.length();
s.write((char*) &stype, sizeof(stype) );
s.write(c.name.c_str(),c.name.length());
s.write((char*) &c.age,sizeof(c.age));
return s;
}

std::istream& operator >> (std::istream& s, character& c)
{
std::string::size_type stype = 0;
s.read((char*) &stype, sizeof(stype) );
char* pstr = new(std::nothrow) char[stype+1];
s.read(pstr,stype);
pstr[stype] = '\0';
c.name = pstr;
delete [] pstr;

s.read((char*) &c.age,sizeof(c.age));
return s;
}

int main()
{
std::ofstream ofile("game.dat", std::ios_base::out | std::ios_base::trunc
| std::ios::binary);

character c1("pippo");

ofile << c1;
ofile.close();

std::ifstream ifile("game.dat", std::ios_base::in | std::ios::binary);

character c2;

ifile >> c2;
ifile.close();

return 0;
}

I hope this simple code can help you.
Fabio
Jul 19 '05 #6

P: n/a

"Thomas Matthews" <th*************@sbcglobal.net> wrote in message
news:3F**************@sbcglobal.net...
3. The binary format of the fields _may_ not be portable across
platforms or compiler implementations.
So why, in your sample, don't you use any signature to identify memory model
(little-endian or big-endian) while saving the integer field ?
4. DO NOT USE OPERATOR<<. The operator is for formatted data,
not unformatted binary data.


Thanks. I forgot that important point.

Fabio
Jul 19 '05 #7

P: n/a
Fabio wrote:
"Thomas Matthews" <th*************@sbcglobal.net> wrote in message
news:3F**************@sbcglobal.net...
3. The binary format of the fields _may_ not be portable across
platforms or compiler implementations.

So why, in your sample, don't you use any signature to identify memory model
(little-endian or big-endian) while saving the integer field ?


Imagine the size of adding an additional byte for every multibyte
value (not including text).

One could save the Endianess at the beginning of the file.
That would be one flag instead of many.

If you need to deal with Endianism, you could read the value
into a buffer then pass the buffer through an endianism filter.
The filter would swap bytes if necessary. The filter could
be activated based on the header information.

Endianess is no problem if and only if the file stays on
the same platform.

If the file is to be used across platforms, try using
ASCII formatted numbers. Most systems can convert an ASCII
number into native format. The C++ language even has
facilities for this.

Otherwise one has to flag the platform specifics such as
endianess, bits per value and floating point format.

Also, my sample was not complete, but enough to give
you an idea and basis to build upon. I didn't supply
code for buffer support and inheritance.

4. DO NOT USE OPERATOR<<. The operator is for formatted data,
not unformatted binary data.

Thanks. I forgot that important point.

Fabio

--
Thomas Matthews

C++ newsgroup welcome message:
http://www.slack.net/~shiva/welcome.txt
C++ Faq: http://www.parashift.com/c++-faq-lite
C Faq: http://www.eskimo.com/~scs/c-faq/top.html
alt.comp.lang.learn.c-c++ faq:
http://www.raos.demon.uk/acllc-c++/faq.html
Other sites:
http://www.josuttis.com -- C++ STL Library book

Jul 19 '05 #8

This discussion thread is closed

Replies have been disabled for this discussion.