CFile and UNICODE

Ah hello.

I am writing out a CMyClass object (very simple class, contains a couple of integers and a BOOL) using CFile

      CFile f;
      if( !f.Open( _T("C:\\Test.txt"), CFile::modeCreate | CFile::modeWrite | CFile::typeBinary ) ) ASSERT(FALSE);
      CMyClass myClass(1, 2, TRUE);
      f.Write((void*)&myClass, sizeof(myClass));

      f.Close();

      if( !f.Open( _T("C:\\Test.txt"), CFile::modeRead | CFile::typeBinary ) ) ASSERT(FALSE);
      CMyClass* pmyClass = new CMyClass();
      f.Read((void*)pmyClass, sizeof(CMyClass));

and all this works fine.

My concern is now that I am thinking about adding a CString member to the class, I dont want to break anything if the CString contains foreign characters.  

In short, is what I am currently doing going to be UNICODE safe ?

TIA
LVL 19
mrwad99Asked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

rajeev_devinCommented:
>> I am thinking about adding a CString member to the class
If you add CString then it won't work the same way.
0
AndyAinscowFreelance programmer / ConsultantCommented:
0
rajeev_devinCommented:
What you are doing is storing the contents of the object.
>> CMyClass myClass(1, 2, TRUE);
>> f.Write((void*)&myClass, sizeof(myClass));

If you add CString
class CMyClass
{
   int x;
   CString str;
}

CMyClass::CMyClass()
{
   x = 10;        // 4 bytes
   str = "Hello world" // 11 bytes
}

You are expection the sizeof the object to be 15 (4+11).
But it is not, because CString just contains one pointer.

In that case you will just copy the pointer value.
0
Get your problem seen by more experts

Be seen. Boost your question’s priority for more expert views and faster solutions

mrwad99Author Commented:
>> If you add CString then it won't work the same way.

Hmm.  That is useful.  Care to elaborate on why ?

Andy:  thanks.  I think I saw that link before, and it made me decide to use serialisation instead.  Maybe that too is the answer here...
0
mrwad99Author Commented:
Thanks for that rajeev_devin.

Interestingly, I did try this, and I did notice that no matter how long the CString, the size was consistent.  The code did not crash however, and the read CString was the same as the stored CString.

Why could that have been ?
0
mrwad99Author Commented:
Overall, is there any way I can use CFile::Write and still output a string ?  Could I use a TCHAR[] or something ?

Or is serialisaion the only answer ?

TIA
0
rajeev_devinCommented:
Are you writing and reading in the same object ???
0
rajeev_devinCommented:
>> Overall, is there any way I can use CFile::Write and still output a string ?  Could I use a TCHAR[] or something ?
That is better.
0
rajeev_devinCommented:
You can use TCHAR array. But remember not pointer.
Something like this
class CMyClass
{
   int x;
   TCHAR[1000];
}
0
AndyAinscowFreelance programmer / ConsultantCommented:
In CMyClass have two functions Read, Write each of which takes a CFile pointer.
That way the class takes care of itself - change the class, change the code inside the class.


Back to UNICODE.
I am not certain if the CFile class is *really* suitable with UNICODE - some things I read say it isn't, hence the link I posted.  It may allow you to write safe code inside the CMyClass where it reads/writes the UNICODE strings to the text file.
0
mrwad99Author Commented:
rajeev_devin

This is my code:

class CMyClass : public CObject
{
 public:
      CMyClass() {}
      CMyClass(int i, int j, BOOL b, CString str)
      {
            m_n1 = i;
            m_n2 = j;
            m_bBOOL = b;
            m_strString = str;
      }
      virtual ~CMyClass(void) {};
      
      int m_n1, m_n2;
      BOOL m_bBOOL;
      CString m_strString;
};

//...

      if( !f.Open( _T("C:\\Test.txt"), CFile::modeWrite | CFile::modeCreate | CFile::typeBinary )) ASSERT(FALSE);
      CMyClass myClass( 10, 20, TRUE, _T("This is my string") );
      f.Write((void*)&myClass, sizeof(myClass));
      size_t size = sizeof(myClass);
      f.Close();

      if( !f.Open( _T("C:\\Test.txt"), CFile::modeRead | CFile::typeBinary ) ) ASSERT(FALSE);
      CMyClass* pmyClass = new CMyClass();
      f.Read((void*)pmyClass, sizeof(CMyClass));

And this works fine!  'pmyClass' has the same values as 'myClass' !

?!
0
AndyAinscowFreelance programmer / ConsultantCommented:
Look at test.txt with notepad - see what has been written.

Now do something really dim and change the order of the variables and read the file (don't overwrite it first).  IMHO it is safer (and better coded?) to encapsulate the read/write inside the CMyClass itself.  Changes you then make to CMyClass are hidden from the rest of the app, you don't need to search all over the place for code snippets to update.
0
rajeev_devinCommented:
This is correct the value will be same. Why?
Because in both case CString in pointing to the same address.
0
mrwad99Author Commented:
Yes, that is an excellent point.  Also, what if I add new members ?  That screws it up totally.

I think serialisation with versioning is the way to go.

I will close this once feedback is received as to why the code I posted works, when in theory it should not.

Thanks.
0
rajeev_devinCommented:
>> CMyClass myClass( 10, 20, TRUE, _T("This is my string") );
>> f.Write((void*)&myClass, sizeof(myClass));
>> f.Close();
CString of myClass is pointing to a location that you are storing using Write.

>> if( !f.Open( _T("C:\\Test.txt"), CFile::modeRead | CFile::typeBinary ) ) ASSERT(FALSE);
>> CMyClass* pmyClass = new CMyClass();
>> f.Read((void*)pmyClass, sizeof(CMyClass));
Now the CString of pmyClass has the same address as myClass.
Therefore, it is pointing to the same data.

I hope its clear.
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
mrwad99Author Commented:
>> Because in both case CString in pointing to the same address

Sorry, I dont get that.  What CString are you talking about ?  I construct two objects, so each has a different address.

?
0
rajeev_devinCommented:
>> Yes, that is an excellent point.
It is like that.
If you want to see the difference then in your program just read the value of that file.
You will see that the CString is garbage.

Do this

CFile f;
if( !f.Open( _T("C:\\Test.txt"), CFile::modeRead | CFile::typeBinary ) ) ASSERT(FALSE);
CMyClass* pmyClass = new CMyClass();
f.Read((void*)pmyClass, sizeof(CMyClass));
0
AndyAinscowFreelance programmer / ConsultantCommented:
mrwad99 - you might have missed my last comment.
0
rajeev_devinCommented:
>> Sorry, I dont get that.  What CString are you talking about ?
Simple example. I am excluding the ctor and dtor.

class CMyClass {
   m_strString; // It is pointing to the string in location say 1000.
};

CMyClass myClass("This is a test");
write(&myClass, ...);

CMyClass* pmyClass = new CMyClass();
Read(pmyClass, sizeof(CMyClass));

value of

pmyClass
{
   // 1000 which is the same string.
}
0
mrwad99Author Commented:
Ha !

I absolutely see the problem.  Adding an explicit call to

      myClass.~CMyClass();

before reading back from the file shows that pmyFile has an m_strString member that is full of rubbish.

Overall, I am going to use serialisation, mainly as a result of what Andy said about adding/changing variables etc.

Thanks both, I will close this now :)
0
rajeev_devinCommented:
>> I construct two objects, so each has a different address.
As I said before CString class only contains a pointer. Something like this

CString {
   char* data; // Here is the pointer.
}

Therefore its size will be 4. Always
0
rajeev_devinCommented:
I don't know whether the thing is clear to you ?
0
mrwad99Author Commented:
I have posted a follow on to this at http:Q_21795040.html

Any participation welcome :)
0
mrwad99Author Commented:
rajeev_devin: yes, your explanation was excellent.  I understand why I cannot use CString in the manner I was doing.  Thank you.
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
System Programming

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.