Public Group

# Files Streams in Binary mode

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

## 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 on other sites
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 itemtemplate <typename T>T read(istream &is) {  T result;  is.read(reinterpret_cast<char*>(&result), sizeof(result));  return result;}// Initialize existing itemtemplate <typename T>void read(istream &is, T &blank) {  is.read(reinterpret_cast<char*>(&blank), sizeof(blank));}// Output itemtemplate <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 itemtemplate <typename T>T read(istream &is) {  return T(is);}// Initialize existing itemtemplate <typename T>void read(istream &is, T &blank) {  blank = T(is); // using assignment operator  // or: is >> blank; using an istream operator>> definition}// Output itemtemplate <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]

##### Share on other sites
serialization? i'm not familiar with that term.

##### 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 on other sites
Quote:
 Original post by SirLuthorIf 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.

• 12
• 9
• 13
• 41
• 15