Programming Forums
User Name Password Register
 

RSS Feed
FORUM INDEX | TODAY'S POSTS | UNANSWERED THREADS | ADVANCED SEARCH

Reply
 
Thread Tools Display Modes
Old Jun 3rd, 2006, 10:14 AM   #1
eagle331
Newbie
 
Join Date: Jun 2006
Posts: 2
Rep Power: 0 eagle331 is on a distinguished road
C++ Binary Input/Output

Hey everybody,

I've got a few problems with binary input/output. I do this in the following way:

<< output
object var1 = ....;
std::string var2 = ....;
ofstream output( fileName.c_str(), ios::out | ios::binary);
output.write( (char*) (&var1), sizeof( var1));
output.write( (char*) (&var2), sizeof( var2));
...etc...
output.close();

>> input
object var1 = ...;
std::string var2 = ...;
ifstream input( fileName.c_str(), ios::in | ios::binary);
input.read( (char*) (&var1), sizeof( var1));
input.read( (char*) (&var2), sizeof( var2));
...etc...
input.close();

The 'object' is a class with members like: std::string and some other custom classes. Now this gives me seg faults because of the dynamic strings. So I tried it using the following code:

size = var1.byteSize();
output.write( (char*) ( &size), sizeof( int));
output.write( (char*) ( &var1), size);

I save the size of each object, but this crashes as well.

So my question to all of you is: can you please give me some good directions for binary I/O ?
eagle331 is offline   Reply With Quote
Old Jun 3rd, 2006, 10:56 AM   #2
Narue
Professional Programmer
 
Narue's Avatar
 
Join Date: Sep 2005
Posts: 419
Rep Power: 4 Narue is on a distinguished road
You can't treat non-POD types as a sequence of bytes. Ever. You probably need to create a new member function that returns a byte string which you can use as the argument to write.
__________________
Even if the voices aren't real, they have some pretty good ideas.
Narue is offline   Reply With Quote
Old Jun 3rd, 2006, 10:58 AM   #3
volatile
Newbie
 
Join Date: Nov 2005
Posts: 18
Rep Power: 0 volatile is on a distinguished road
You are doing alot of things wrong here.
output.write( (char*) (&var1), sizeof( var1));
output.write( (char*) (&var2), sizeof( var2));

(char*)&var1 will return the address of the var1 object, not the string data you want to write. The string class contains alot of data members, one of wich is a pointer to the acutal string with your data. Your method will only output crap data. (char*)var1 would seem better, only problem, the string class does not provide a (char*) conversion operator. It does however have this operator char& operator[]( size_type index ); which you can use to get the first element.

sizeof(var1) and sizeof(var2) is exactly the same. It returns the size of the string class, not the string data. use the size method to get the string length.

output.write( (char*) (&var1), sizeof( var1));  // wrong
outfile.write((char*)&var1[0], var1.size());     // works

Ansi C++ does not guarantee that the stl string is stored sequential in memory, however I dont know know of an implementation that does otherwise. So it probarbly will work.

But why not just do it like this:
outfile << var1
volatile is offline   Reply With Quote
Old Jun 3rd, 2006, 11:05 AM   #4
volatile
Newbie
 
Join Date: Nov 2005
Posts: 18
Rep Power: 0 volatile is on a distinguished road
Oops. I thought var1 and var2 were both strings. Anyway, what I said applies to the string type.
volatile is offline   Reply With Quote
Old Jun 3rd, 2006, 11:27 AM   #5
eagle331
Newbie
 
Join Date: Jun 2006
Posts: 2
Rep Power: 0 eagle331 is on a distinguished road
Ok, so the best way to do this with objects is to serialise it ? Every class has to have a function that returns a char* that contains all the objects sequential.
eagle331 is offline   Reply With Quote
Old Jun 3rd, 2006, 12:09 PM   #6
DaWei
Resident Grouch
 
DaWei's Avatar
 
Join Date: Jun 2005
Posts: 6,453
Rep Power: 10 DaWei is on a distinguished road
I think it's fair to ask if you even know what you mean by the term, "binary I/O". I'm relatively sure we don't know what you mean, even if you do.
__________________
Abstraction doesn't make it impossible to write bad code; it makes it possible to write superior code.
Contributor's Corner: Grumpy on C++ Exceptions DaWei on Pointers
DaWei is offline   Reply With Quote
Old Jun 3rd, 2006, 12:36 PM   #7
volatile
Newbie
 
Join Date: Nov 2005
Posts: 18
Rep Power: 0 volatile is on a distinguished road
Quote:
Ok, so the best way to do this with objects is to serialise it ? Every class has to have a function that returns a char* that contains all the objects sequential.
hmm. not sure what you mean about serializing your objects.

I have to correct myself a little bit. string has a c_str() (as you used in your code) method that return char*. Your string data is stored sequentialy. I was thinking vectors. I wasnt thinking straight. Anyway, as for your 'object'. I dont know how its designed, what data does it hold. Does it contain dynamic stream of data just like string, if so you can make a (char*) conversion operator. Something like this.
operator char*()
{
     return data_; // data_ is pointer to your data
}

and also a size method, then its easy to write it to disk:

output.write( (char*)&var1, var1.size());

If it has many data members you want to write to file, maybe having a write method passing it a ofstream object would be a solution.

object::write(ofstrea& file)
{
// write your data to file here
}

Perhaps your object only has fixed data member, no allocated shit. you may do like you originaly did:
output.write( (char*) (&var1), sizeof( var1));
Although not very portable. Theres an issue with little and big endian. If you store on a machine with little endian, the read on a big endian system, the data will be all wrong.
volatile is offline   Reply With Quote
Old Jun 3rd, 2006, 1:40 PM   #8
Narue
Professional Programmer
 
Narue's Avatar
 
Join Date: Sep 2005
Posts: 419
Rep Power: 4 Narue is on a distinguished road
>Ok, so the best way to do this with objects is to serialise it ?
The only way to do this is to serialize it. You said your object contains std::strings and other classes, so it's not POD. You can't pun non-POD types into an array of bytes because you'll be accessing untouchable regions of the data. That could crash immediately if you hit a trap representation, or you could just corrupt everything and it'll crash later. Either way, it doesn't do what you want.
__________________
Even if the voices aren't real, they have some pretty good ideas.
Narue is offline   Reply With Quote
Reply

Bookmarks

« Previous Thread in Forum | Next Thread in Forum »

Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Forum Jump




DaniWeb IT Discussion Community
All times are GMT -5. The time now is 6:00 PM.

Powered by vBulletin® Version 3.7.0, Copyright ©2000 - 2009, Jelsoft Enterprises Ltd.
Copyright ©2007 DaniWeb® LLC