Link to home
Start Free TrialLog in
Avatar of SileNcer
SileNcer

asked on

Binary streaming a CString with fstream

Hi, I'm new at using .write() and .read() functions of istream's and ostream's.  It seems that when I write or read a struct to a file that contains CStrings in it's data memebers, they are not written correctly.  Can anyone tell me how to go about writting a CString in binary format?
Avatar of tdubroff
tdubroff

Can you post your current code?
USE the function GetBuffer()in CString class it will return to you the char* string, so you can writh car* in file.

Maydipalle
Avatar of SileNcer

ASKER

//here is an example of my code:

struct score_type
{
      int score1,score2,score3;
      char name1[1],name2[1],name3[1],
           message[1];
};

score_type high;
high.name1 = "Player1";
high.name2 = "Player2";
high.name3 = "Player3";
high.score1 = 3;
high.score2 = 2;
high.score3 = 1;

ostream out_file;
out_file.open("data.dat");
out_file.write((const char*)
  &high,sizeof(score_type));

//when read back in with the command,
//in_file.read((char*)&score,
//  sizof(score_type));
//the strings are messed up
Avatar of Jan Louwerens
if you're already using streams,  the best way is just to use the << and >> operators. I assume Microsoft was smart enough to implement serialization in CString.

CString str = "foo";
ofstream outfile(filename, ios::binary);
outfile << str;

---

CString str;
ifstream infile(filename, ios::binary);
infile >> str;
Maydipalle,
Could you please show me an example?  And can I use this method while writing the whole struct, or must I write each data memeber seperatly?  Thank you.
you're also overwriting your array boundaries in all 3 of your "char name[1]" variables. You're only allocating one character for each array, then filling each with 7 character strings (8 with null terminator!).
OPPS, sorry.. those chars are supposed to be CStrings...

struct score_type
{
int score1,score2,score3;
CSring name1,name2,name3,
           message;
};

if your using MFC, I would stringly suggest you use CStrings instead of char*. If your not using MFC, you should use the string class from the STL. Either of those classes will work with the shift operators (<< and >>)  mentioned above
This is an MFC application, which is why I am having so much trouble.  Char arrays do not work well with it.
Ok, I will try the ios::binary.  But could you tell me the difference between .write() and when I should use it rather then the '<<'?  I have increased the points for your trouble.
Adjusted points to 150
ASKER CERTIFIED SOLUTION
Avatar of tdubroff
tdubroff

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
well, read() and write() are old functions, still around from the days of C... there are better alternatives to those functions in C++.  Also, MFC hase some classes (I forget which, exactly) for file IO, which should also make things easier.

In your project, you can't just write the entire struct to the file. Each member in the struct must be written to the file separately. Without getting into serialization, or stream friend functions, you could make your struct a class and add Save(), Load() functions.

void Save(ofstream outfile)
{
   outfile << score1 << score2 << score3;
   outfile << name1 << name2 << name3;
   outfile << message;
}

void Load(ifstream infile)
{
   infile >> score1 >> score2 >> score3;
   infile >> name1 >> name2 >> name3;
   infile >> message;
}
the ios::binary applies to the file, not the function. It indicates that you want a binary file (as opposed to a text file)
2 cases, on my machine they do the same thing:
#include <fstream.h>
void main()
{
    ofstream ofile("test.txt", ios::out);
    ofile << 3.2;
}

#include <fstream.h>
void main()
{
    ofstream ofile("test.txt", ios::out | ios::binary);
    ofile << 3.2;
}

Both times the file has the ASCII 3.2 in it and nothing else.
Ok, you both have lead me to this method of solving my problem.  Here is what I have decided to do, tell me if there is a better way:
1st, I create my ostream and for none strings, I use .write().  When I come across strings, I'll use the << along with a '\n' to seperate the data.
2nd, I create a istream and read in all the none strings with .read() and all the strings with .getline().

So, far it works really well and I can reuse a lot of my code; i was using the <<'s orginally, but i wanted to convert to binary.
//Here is a test code I used that
//worked rather well

CString m_name = "Player1";
MessageBox(m_name);
char test[20];
int num = 1999;
int num2;
ofstream out_file;
out_file.open("data.txt", ios::binary);
out_file << m_name + '\n';
out_file.write((const char*)&num,sizeof(int));
out_file.close();
ifstream in_file2;
in_file.open("data.txt", ios::binary);
in_file.getline(test,20);
in_file.read((char*)&num2,sizeof(int));
wsprintf(str,"%i   ",num2);
in_file.close();
MessageBox(test);
MessageBox(str);
If this is the best way, then i would like tdubroff to submit an answer to this question now because he commented first.  But, you both have contributed equally and helped me out a great deal and I think you both deserve 150pts each.  So, after this question is answered, I will submit another question for jlouwere to respond to for his 150pts.
Thank you both very much

ah yes. you are correct. I guess you learn something new every day, huh?

ok, so, to correct myself from earlier, you still want to use read() and write() when you want to store the data as binary within the file.

(I guess I was just getting confused between stream shift operators and the MFC serialization mechanism)
you don't have to wait for an answer, you can accept any comment as an answer (except your own, of course). You can go ahead and give the points to tdubroff. It won't bother me a bit. I'm just glad I could help out.

tdubroff, in my testing I have noticed that the << and >> operators always write the data out as text no what mode the file was opened in, and the read() and write() functions always write the data out as binary.

SileNcer, since you're using MFC already, why not use the MFC file I/O classes?
Does that mean I do not have to use ios::binary when opening a file?
I have not had any experience with the MFC file I/O classes; this is my first semester of college.  I am however interested in researching it, perhaps over my Christmas break next week :-]
jlouwere, i have posted another question for you because i believe you also deserve the points.

Thank you both