mrwad99
asked on
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
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
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.
>> 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.
ASKER
>> 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...
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...
ASKER
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 ?
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 ?
ASKER
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
Or is serialisaion the only answer ?
TIA
Are you writing and reading in the same object ???
>> 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.
That is better.
You can use TCHAR array. But remember not pointer.
Something like this
class CMyClass
{
int x;
TCHAR[1000];
}
Something like this
class CMyClass
{
int x;
TCHAR[1000];
}
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.
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.
ASKER
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' !
?!
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' !
?!
SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
This is correct the value will be same. Why?
Because in both case CString in pointing to the same address.
Because in both case CString in pointing to the same address.
ASKER
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.
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.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
>> 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.
?
Sorry, I dont get that. What CString are you talking about ? I construct two objects, so each has a different address.
?
>> 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));
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));
mrwad99 - you might have missed my last comment.
>> 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.
}
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.
}
ASKER
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 :)
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 :)
>> 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
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
I don't know whether the thing is clear to you ?
ASKER
ASKER
rajeev_devin: yes, your explanation was excellent. I understand why I cannot use CString in the manner I was doing. Thank you.
If you add CString then it won't work the same way.