C Board  

Go Back   C Board > General Programming Boards > C++ Programming

Reply
 
LinkBack Thread Tools Display Modes
Old 06-21-2009, 04:19 AM   #1
Darkness Prevails
 
Dark_Phoenix's Avatar
 
Join Date: Oct 2006
Location: Houston, Texas
Posts: 174
read / write binary files

I have two questions with reading / writing complex data in a binary file. I have this code which saves a complex type (struct) in a binary file.
Code:
#include <iostream>
#include <string>
#include <fstream>
 
struct DATA
{
    std::string  s1;
    std::string  s2;
    int          i1;
    int          i2;
    std::string  s3;
    double       d1;
    double       d2;
    std::string  s4;
};
 
void Save(DATA &d)
{
    std::ofstream oFile("data.bin", std::ios::out | std::ios::binary);
    oFile.write( (char*)&d, sizeof(d) );
    oFile.close();
    return;
}
 
void Load(DATA &d)
{
    std::ifstream iFile("data.bin", std::ios::in | std::ios::binary);
    iFile.read( (char*)&d, sizeof(d) );
    iFile.close();
    return;
}
 
void Display(DATA &d)
{
    std::cout<<"string 1  = " <<d.s1 <<"\n"
             <<"string 2  = " <<d.s2 <<"\n"
             <<"integer 1 = " <<d.i1 <<"\n"
             <<"integer 2 = " <<d.i2 <<"\n"
             <<"string 3  = " <<d.s3 <<"\n"
             <<"double 1  = " <<d.d1 <<"\n"
             <<"double 2  = " <<d.d2 <<"\n"
             <<"string 4  = " <<d.s4 <<"\n\n\n\n";
    return;
}
 
int main()
{
    DATA x, y;
    x.s1 = "This is some text";
    x.s2 = "This is some more text";
    x.i1 = 5;
    x.i2 = 55423;
    x.s3 = "And some more text";
    x.d1 = 87.12;
    x.d2 = 1123.542;
    x.s4 = "Wait! Here's some more text!!";
    Display(x);
    Save(x);
    Load(y);
    Display(y);
    return 0;
}
#1 : How does the system know the correct size of DATA for the calls to read() and write()? My understading is the objects of type std::string can have a different size depending on the data that it contains.

#2 : Is this legal / safe?
__________________
Using Code::Blocks and Windows XP

In every hero, there COULD be a villain!

Last edited by Dark_Phoenix; 06-21-2009 at 04:21 AM.
Dark_Phoenix is offline   Reply With Quote
Old 06-21-2009, 04:29 AM   #2
Kernel hacker
 
Join Date: Jul 2007
Location: Farncombe, Surrey, England
Posts: 15,686
What you are doing is not legal. You are essentially storing the internal data parts of string class, which IS NOT the string itself. Most of the time, the string will be stored as a pointer to the actual string data. So you'd be storing the pointer. When the data is being read back, you read back the pointer again. If you do this after destroying the original string (or after restarting the application), the pointer will no longer point to the value of the original string.

You supply the size of d to read/write, so that's how it knows (but of course, sizeof(std::string) will be something like 8 or 16, no matter if you have a single character or 500 characters in the string. Becuase the string class itself doesn't store the whole string - only a pointer to strings.

If you want to do this as a binary file, you have two choices:
1. Make it a POD structure - that is, do not use anything that is a class in the storage structure.
2. Use serialization - produce a pair input/output functions that stores the individual components in a form that you can read back reliably.

--
Mats
__________________
Compilers can produce warnings - make the compiler programmers happy: Use them!
Please don't PM me for help - and no, I don't do help over instant messengers.
matsp is offline   Reply With Quote
Old 06-21-2009, 04:38 AM   #3
Darkness Prevails
 
Dark_Phoenix's Avatar
 
Join Date: Oct 2006
Location: Houston, Texas
Posts: 174
Thanks. serialization is what I have been doing when working with std::strings, was just playing around with some ideas. I had a feeling that this would not work right, just did not quite understand what was going on "behind the scenes".

Just so that I understand correct.... If I were to change the std::strings to char arrays, then this would work?
__________________
Using Code::Blocks and Windows XP

In every hero, there COULD be a villain!
Dark_Phoenix is offline   Reply With Quote
Old 06-21-2009, 04:46 AM   #4
Kernel hacker
 
Join Date: Jul 2007
Location: Farncombe, Surrey, England
Posts: 15,686
Quote:
Originally Posted by Dark_Phoenix View Post
Just so that I understand correct.... If I were to change the std::strings to char arrays, then this would work?
Indeed. But they need to be proper arrays, not dynamic arrays using pointers.

By the way, if you split your test-program so that it exits after save, and then loads in a second process, you will see that it doesn't work, even if your current example appears to work.

--
Mats
__________________
Compilers can produce warnings - make the compiler programmers happy: Use them!
Please don't PM me for help - and no, I don't do help over instant messengers.
matsp is offline   Reply With Quote
Old 06-21-2009, 05:34 AM   #5
Darkness Prevails
 
Dark_Phoenix's Avatar
 
Join Date: Oct 2006
Location: Houston, Texas
Posts: 174
OK, I got it... I split my test pogram like you suggested and I see what you mean. So now I have
Code:
struct DATA
{
    char    s1[30];
    char    s2[30];
    int     i1;
    int     i2;
    char    s3[30];
    double  d1;
    double  d2;
    char    s4[30];
};

int main()
{
    DATA x, y;

    strcpy_s(x.s1, sizeof(x.s1), "This is some text");
    strcpy_s(x.s2, sizeof(x.s2), "This is some more text");
    x.i1 = 5;
    x.i2 = 55423;
    strcpy_s(x.s3, sizeof(x.s3), "And some more text");
    x.d1 = 87.12;
    x.d2 = 1123.542;
    strcpy_s(x.s4, sizeof(x.s4), "Wait! Here's some more text!!");

    Display(x);
    Save(x);
    Load(y);
    Display(y);

    return 0;
}
And this seems to work better.
__________________
Using Code::Blocks and Windows XP

In every hero, there COULD be a villain!
Dark_Phoenix is offline   Reply With Quote
Old 06-21-2009, 07:56 AM   #6
The superheterodyne.
 
twomers's Avatar
 
Join Date: Dec 2005
Location: Ireland
Posts: 2,205
You could always template the structure so it will work with string arrays of different sizes. Though, of course, the template size will need to be known at compile time and the functions will have to be templated too.
Code:
template<int arrSize> 
struct DATA
{
    char    s1[arrSize];
    char    s2[arrSize];
    int     i1;
    int     i2;
    char    s3[arrSize];
    double  d1;
    double  d2;
    char    s4[arrSize];
}; 

... 

int main() {
  DATA<30> x, y;

  // etc...

  return 0;
}
__________________
I blag!
twomers is offline   Reply With Quote
Reply

Thread Tools
Display Modes

Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
Merge Binary Files chinook86 C Programming 7 01-21-2008 02:19 PM
Reading Binary files earth_angel C++ Programming 10 07-12-2005 06:48 AM
Binary Files Axpen C Programming 14 08-12-2004 08:41 PM
How to store n write binary file? megablue C Programming 4 10-23-2003 03:53 AM
Serial Communications in C ExDigit Windows Programming 7 01-09-2002 10:52 AM


All times are GMT -6. The time now is 05:53 PM.


Powered by vBulletin® Version 3.8.1
Copyright ©2000 - 2009, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO 3.3.0 RC2

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22