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?
SileNcerAsked:
Who is Participating?
 
tdubroffConnect With a Mentor Commented:
There is not much difference between using write() and <<, except that write() I believe only accepts char*'s while << is overloaded to accept lots of stuff.  Also I don't believe ios::binary is supported with <<, only with write().
0
 
tdubroffCommented:
Can you post your current code?
0
 
MaydipalleCommented:
USE the function GetBuffer()in CString class it will return to you the char* string, so you can writh car* in file.

Maydipalle
0
The new generation of project management tools

With monday.com’s project management tool, you can see what everyone on your team is working in a single glance. Its intuitive dashboards are customizable, so you can create systems that work for you.

 
SileNcerAuthor Commented:
//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
0
 
Jan LouwerensSoftware EngineerCommented:
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;
0
 
SileNcerAuthor Commented:
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.
0
 
Jan LouwerensSoftware EngineerCommented:
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!).
0
 
SileNcerAuthor Commented:
OPPS, sorry.. those chars are supposed to be CStrings...

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

0
 
Jan LouwerensSoftware EngineerCommented:
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
0
 
SileNcerAuthor Commented:
This is an MFC application, which is why I am having so much trouble.  Char arrays do not work well with it.
0
 
SileNcerAuthor Commented:
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.
0
 
SileNcerAuthor Commented:
Adjusted points to 150
0
 
Jan LouwerensSoftware EngineerCommented:
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;
}
0
 
Jan LouwerensSoftware EngineerCommented:
the ios::binary applies to the file, not the function. It indicates that you want a binary file (as opposed to a text file)
0
 
tdubroffCommented:
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.
0
 
SileNcerAuthor Commented:
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.
0
 
SileNcerAuthor Commented:
//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);
0
 
SileNcerAuthor Commented:
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

0
 
Jan LouwerensSoftware EngineerCommented:
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)
0
 
Jan LouwerensSoftware EngineerCommented:
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?
0
 
SileNcerAuthor Commented:
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 :-]
0
 
SileNcerAuthor Commented:
jlouwere, i have posted another question for you because i believe you also deserve the points.

Thank you both


0
All Courses

From novice to tech pro — start learning today.