Jump to content
  • Advertisement
Sign in to follow this  
Lorek

Files Streams in Binary mode

This topic is 4904 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've been working teaching myself C++ for awhile now, I'm working on file streams in binary mode right now. My read and write functions are below. I'm going to be writing and reading custom objects. What i'm having trouble with is finding the best, most dynamic way to write these and return the information retrieved back to my main function. The ways I know how to do this are, in main() obj temp = read(); or setting a point to hold the memory address of the variable returned. I'm pretty sure theres an easier, simpler way to do this but I'm at a loss right now. I'd prefer not to use a global variable. obj read(int num) { obj temp; ifstream infile; infile.open("DATA.DAT", ios::binary); infile.seekg( num*sizeof(Int) ); infile.read( reinterpret_cast<char*>(&temp), sizeof(temp) ); return temp; } void write(obj temp) { ofstream outfile("DATA.DAT", ios::binary); outfile.write(reinterpret_cast<char*>(&temp), sizeof(temp) ); }

Share this post


Link to post
Share on other sites
Advertisement
Don't open the file for each read/write call. Also, don't try to calculate magic file locations and then seek to them. Instead, just read/write one item at a time, having a little wrapper method to handle it.

One option for POD types and primitives would be something like:

// Create new item
template <typename T>
T read(istream &is) {
T result;
is.read(reinterpret_cast<char*>(&result), sizeof(result));
return result;
}

// Initialize existing item
template <typename T>
void read(istream &is, T &blank) {
is.read(reinterpret_cast<char*>(&blank), sizeof(blank));
}

// Output item
template <typename T>
void write(ostream &os, T &item) {
os.write(reinterpret_cast<char*>(&item), sizeof(item));
}



Which is very much like what you already have. However, you should not try to handle anything that's at all complex this way (i.e. if the object contains pointers, has non-trivial ctor/dtor, or in any way cares about its or anything else's location in memory), you should make the class hold the information about how to do the serialization:


// The classes provide methods:
// - ctor taking an istream&
// - either friend istream::operator>>, or a copy ctor and assignment operator
// - friend ostream::operator<<

// Create new item
template <typename T>
T read(istream &is) {
return T(is);
}

// Initialize existing item
template <typename T>
void read(istream &is, T &blank) {
blank = T(is); // using assignment operator
// or: is >> blank; using an istream operator>> definition
}

// Output item
template <typename T>
void write(ostream &os, T &item) {
os << item;
}



If you want to use both, you'll need to do some kind of template magic in order to differentiate POD types from non-POD types. (Or you could just let all your non-trivial classes derive from some 'Serializable' ABC, and specialize the template for that.)

Also, if you want to have both 'text' and 'binary' representations for your objects, and choose one to serialize as/deserialize from at runtime, then obviously you can't really do the job with just << and >>. [smile]

But what do I know? You should read what someone really knowledgable has to say about this serialization stuff.

Share this post


Link to post
Share on other sites
If I recall correctly, serialization is simply the act of turning the data of an object into a stream of bytes that can be written directly to a file (or sent across a network as packets), and re-interpereted into the data when it is read back out again with a corresponding 'un-serialize' method. I'm afraid that was ghastly and most unclear, but, well, methinks you will have to wait until a more knowledgeable person then I comes along to get a better explanation [smile]
Cheers!

Share this post


Link to post
Share on other sites
Quote:
Original post by SirLuthor
If I recall correctly, serialization is simply the act of turning the data of an object into a stream of bytes that can be written directly to a file (or sent across a network as packets), and re-interpereted into the data when it is read back out again with a corresponding 'un-serialize' method. I'm afraid that was ghastly and most unclear, but, well, methinks you will have to wait until a more knowledgeable person then I comes along to get a better explanation [smile]
Cheers!


Yeah, you're right. It's not that important how you save the data, just you can bring it back up to the data structures again.

A good thing could be to implement a class "Serialize" or similar, java does this, with only two methods, in c++ "const std::string serialize()=0;" and "void deserialize(const std::string& input)=0;" and just inherit that interface into whatever class you need serializeable.

This makes sure the class which needs to be serialized/deserialized gets the proper interface, which then the program can rely on when using it.

That way, you can store a list of Serialize object pointers to make sure you load/save all of them at once for instance, just from the top of my head.

And a pretty interface is always a good thing :)

Good luck
Albert "thec" Sandberg

Ps. The =0 thing in the interface class means you _have_ to include those methods in the class which inherits Serialize... Ds.

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!