Strange message during serialization. please help!
-
Hi, I have serialized a tree control which container is a CView derived class. Everything works fine during serialization and unserialization. Tree items display perfectly after Unserialization but a message box displays this text: "Unexpected file format." this message is located in Vc7\atlmfc\include\afxres.rc( line 74): AFX_IDP_FAILED_INVALID_FORMAT "Unexpected file format." I’ve tried to find the reason of this message and also found a thread talking of the same problem @ : http://www.codeguru.com/forum/showt...ization+pointer But no solution is provided. Could you please help me resolve this issue? I use VS 2003 my application is based on an MDI document view and the message occurs in the debug and release version. Many thanks for your help
-
Hi, I have serialized a tree control which container is a CView derived class. Everything works fine during serialization and unserialization. Tree items display perfectly after Unserialization but a message box displays this text: "Unexpected file format." this message is located in Vc7\atlmfc\include\afxres.rc( line 74): AFX_IDP_FAILED_INVALID_FORMAT "Unexpected file format." I’ve tried to find the reason of this message and also found a thread talking of the same problem @ : http://www.codeguru.com/forum/showt...ization+pointer But no solution is provided. Could you please help me resolve this issue? I use VS 2003 my application is based on an MDI document view and the message occurs in the debug and release version. Many thanks for your help
Are you using CObject serialization? Are you positive your serialize and unserialize code writes and reads the exact same number of bytes to/from the file? Mark
"Posting a VB.NET question in the C++ forum will end in tears." Chris Maunder
-
Are you using CObject serialization? Are you positive your serialize and unserialize code writes and reads the exact same number of bytes to/from the file? Mark
"Posting a VB.NET question in the C++ forum will end in tears." Chris Maunder
Yes I use CObject Serialization. About data storing and loading I indent the storing and I use "\r\n" to skip to the next line. I have attached the code for your review.
void BnBSymbolTreeCtrl::Serialize(CArchive& ar)
{BnBSymbolInfos\* pInfo = NULL; TVITEM tvi = {0}; UINT state = NULL; ; LPARAM param = NULL ; UINT mask = TVIF\_HANDLE |TVIF\_PARAM|TVIF\_IMAGE|TVIF\_SELECTEDIMAGE|TVIF\_STATE|TVIF\_TEXT; int nImage = NULL; int nSelectedImage = NULL; if (ar.IsStoring()) { // storing code HTREEITEM hti = GetRootItem(); while( hti ) { //Get node data from TVITEM to define which images are attached to the item tvi.mask = TVIF\_HANDLE |TVIF\_PARAM; tvi.hItem =hti ; GetItem(&tvi); LPARAM param = tvi.lParam; int nImage; int nSelectedImage; GetItemImage(hti, nImage, nSelectedImage); UINT state = GetItemState(hti,TVIS\_BOLD); UINT ste = tvi.state; CString str = GetItemText( hti ); int indent = GetIndentLevel( hti ); while( indent -- ) ar.WriteString( "\\t" );//serialize the indent level ar.WriteString( GetItemText( hti ) + "\\r\\n");//Serialize node name ar << state << param << nImage << nSelectedImage;//Serialize the node properties ar.WriteString("\\r\\n" );//go to the next line pInfo = m\_SymbolInfo.GetSymbolInfoObject(hti); if(pInfo) ar << pInfo->lparam;//seriliaze the symbolinfo related to the node ar.WriteString("\\r\\n" );//go to the next line hti = GetNextNearItem( hti ); } }
//Loading from Archive section
else
{CString sLine; if(!ar.ReadString( sLine ) ) return; //be sure the tree is cleaned before loading DeleteAllItems( ); HTREEITEM hti = NULL; int indent, baseindent = 0; CString strReturn = "\\r\\n"; while( sLine\[baseindent\] == '\\t' ) baseindent++; do { if( sLine.GetLength() == 0 ) continue; for( indent = 0; sLine\[indent\] == '\\t'; indent++ ) ; // We don't need a body sLine = sLine.Right( sLine.GetLength() - indent ); indent -= baseindent; HTREEITEM parent; int previndent = GetIndentLevel( hti ); if( indent == previndent) parent = GetParentItem( hti ); else if( indent > previndent ) parent = hti; else { int nLevelsUp = previndent - indent; parent = GetParentItem( hti ); while( nLevelsUp-- ) parent = GetParentItem( parent ); } ar >> state >> param >> nImage >> nSelectedImage;//upload the node properties ar.ReadString(
-
Yes I use CObject Serialization. About data storing and loading I indent the storing and I use "\r\n" to skip to the next line. I have attached the code for your review.
void BnBSymbolTreeCtrl::Serialize(CArchive& ar)
{BnBSymbolInfos\* pInfo = NULL; TVITEM tvi = {0}; UINT state = NULL; ; LPARAM param = NULL ; UINT mask = TVIF\_HANDLE |TVIF\_PARAM|TVIF\_IMAGE|TVIF\_SELECTEDIMAGE|TVIF\_STATE|TVIF\_TEXT; int nImage = NULL; int nSelectedImage = NULL; if (ar.IsStoring()) { // storing code HTREEITEM hti = GetRootItem(); while( hti ) { //Get node data from TVITEM to define which images are attached to the item tvi.mask = TVIF\_HANDLE |TVIF\_PARAM; tvi.hItem =hti ; GetItem(&tvi); LPARAM param = tvi.lParam; int nImage; int nSelectedImage; GetItemImage(hti, nImage, nSelectedImage); UINT state = GetItemState(hti,TVIS\_BOLD); UINT ste = tvi.state; CString str = GetItemText( hti ); int indent = GetIndentLevel( hti ); while( indent -- ) ar.WriteString( "\\t" );//serialize the indent level ar.WriteString( GetItemText( hti ) + "\\r\\n");//Serialize node name ar << state << param << nImage << nSelectedImage;//Serialize the node properties ar.WriteString("\\r\\n" );//go to the next line pInfo = m\_SymbolInfo.GetSymbolInfoObject(hti); if(pInfo) ar << pInfo->lparam;//seriliaze the symbolinfo related to the node ar.WriteString("\\r\\n" );//go to the next line hti = GetNextNearItem( hti ); } }
//Loading from Archive section
else
{CString sLine; if(!ar.ReadString( sLine ) ) return; //be sure the tree is cleaned before loading DeleteAllItems( ); HTREEITEM hti = NULL; int indent, baseindent = 0; CString strReturn = "\\r\\n"; while( sLine\[baseindent\] == '\\t' ) baseindent++; do { if( sLine.GetLength() == 0 ) continue; for( indent = 0; sLine\[indent\] == '\\t'; indent++ ) ; // We don't need a body sLine = sLine.Right( sLine.GetLength() - indent ); indent -= baseindent; HTREEITEM parent; int previndent = GetIndentLevel( hti ); if( indent == previndent) parent = GetParentItem( hti ); else if( indent > previndent ) parent = hti; else { int nLevelsUp = previndent - indent; parent = GetParentItem( hti ); while( nLevelsUp-- ) parent = GetParentItem( parent ); } ar >> state >> param >> nImage >> nSelectedImage;//upload the node properties ar.ReadString(
I'm suspicious (:suss:) about your serialization of "pInfo->lparam"... When storing you do this:
pInfo = m_SymbolInfo.GetSymbolInfoObject(hti);
if(pInfo)
ar << pInfo->lparam;//seriliaze the symbolinfo related to the nodeWhen loading you do this:
ar >> pInfo->lparam;
if(pInfo)//link the symbolinfo to its related node
{
if(pInfo->lparam == tvi.lParam)If you have a conditional write when storing then you should store something if the condition fails - otherwise at load time you don't know if you should load the next value from the stream or not. For example, if when storing, if "if(pInfo)" is false, pInfo->lparam is not archived. When you load from the archive, you read pInfo->lparam unconditionally - but it won't be there. Now the stream is off by sizeof(pInfo->lparam) bytes. Make sense? Also, when loading, you create an object... pInfo = new BnBSymbolInfos(); ...use the object... ar >> pInfo->lparam; ...Then check if the object is NULL if(pInfo)//link the symbolinfo to its related node That makes the NULL check useless :) Mark
"Posting a VB.NET question in the C++ forum will end in tears." Chris Maunder
-
I'm suspicious (:suss:) about your serialization of "pInfo->lparam"... When storing you do this:
pInfo = m_SymbolInfo.GetSymbolInfoObject(hti);
if(pInfo)
ar << pInfo->lparam;//seriliaze the symbolinfo related to the nodeWhen loading you do this:
ar >> pInfo->lparam;
if(pInfo)//link the symbolinfo to its related node
{
if(pInfo->lparam == tvi.lParam)If you have a conditional write when storing then you should store something if the condition fails - otherwise at load time you don't know if you should load the next value from the stream or not. For example, if when storing, if "if(pInfo)" is false, pInfo->lparam is not archived. When you load from the archive, you read pInfo->lparam unconditionally - but it won't be there. Now the stream is off by sizeof(pInfo->lparam) bytes. Make sense? Also, when loading, you create an object... pInfo = new BnBSymbolInfos(); ...use the object... ar >> pInfo->lparam; ...Then check if the object is NULL if(pInfo)//link the symbolinfo to its related node That makes the NULL check useless :) Mark
"Posting a VB.NET question in the C++ forum will end in tears." Chris Maunder
You're right about this piece of code but actually it is not responsible of the problem. With this simple code, storing and loading is ok but I still get this nasty message box after loading.:confused: any idea?
void BnBSymbolTreeCtrl::Serialize(CArchive& ar)
{
HTREEITEM hti = NULL;
if (ar.IsStoring())
{
hti = GetRootItem();
ar.WriteString( GetItemText( hti ));
}else { CString sLine; ar.ReadString( sLine ); hti = InsertItem( sLine, TVI\_ROOT, TVI\_LAST ); }
}
-
You're right about this piece of code but actually it is not responsible of the problem. With this simple code, storing and loading is ok but I still get this nasty message box after loading.:confused: any idea?
void BnBSymbolTreeCtrl::Serialize(CArchive& ar)
{
HTREEITEM hti = NULL;
if (ar.IsStoring())
{
hti = GetRootItem();
ar.WriteString( GetItemText( hti ));
}else { CString sLine; ar.ReadString( sLine ); hti = InsertItem( sLine, TVI\_ROOT, TVI\_LAST ); }
}
Hmm - You aren't using the same archive object for both serializing and unserializing are you? Or using the same CFile without calling SeekToBegin()? Can you show the code that creates the CFIles and CArchives used when it fails? Mark
"Posting a VB.NET question in the C++ forum will end in tears." Chris Maunder
-
Hmm - You aren't using the same archive object for both serializing and unserializing are you? Or using the same CFile without calling SeekToBegin()? Can you show the code that creates the CFIles and CArchives used when it fails? Mark
"Posting a VB.NET question in the C++ forum will end in tears." Chris Maunder
I call Serialize from the CDocument derived class's Serialize method. This function is called when selecting save and open menus. in the meantime I'm wondering if CArchive can t support mixing types and especially the ReadString and AddString functions. Below is my finding
void BnBSymbolTreeCtrl::Serialize(CArchive& ar)
{
CString str;
CString str1 = "Root";
char* pchr= "Root";if (ar.IsStoring()) { //ar.WriteString( "Root");//Messagebox warning //ar.WriteString( str1);//Messagebox warning //ar.WriteString( pchr);//Messagebox warning //ar << pchr; //Messagebox warning ar << str1; //OK. } else { //ar.ReadString( str ); ar >> str; InsertItem( str, TVI\_ROOT, TVI\_LAST ); }
}
-
I call Serialize from the CDocument derived class's Serialize method. This function is called when selecting save and open menus. in the meantime I'm wondering if CArchive can t support mixing types and especially the ReadString and AddString functions. Below is my finding
void BnBSymbolTreeCtrl::Serialize(CArchive& ar)
{
CString str;
CString str1 = "Root";
char* pchr= "Root";if (ar.IsStoring()) { //ar.WriteString( "Root");//Messagebox warning //ar.WriteString( str1);//Messagebox warning //ar.WriteString( pchr);//Messagebox warning //ar << pchr; //Messagebox warning ar << str1; //OK. } else { //ar.ReadString( str ); ar >> str; InsertItem( str, TVI\_ROOT, TVI\_LAST ); }
}
Ok I've been digging through the source code. I'm on MFC 7.1 (VS2003) I'm not sure how this compiles since there's no insertion/extraction operators that take a CString: CString str; CString str1 = "Root"; ... ar << str1; ... ar >> str; The only way I see to write and read a CString is: CString str; CString str1 = "Root"; ... ar.WriteString( (LPCTSTR)str1 ); ar << _T('\n'); ... ar.ReadString( str ); FWIW I hated this about CArchive. I use my own CArchive-derived class which writes strings using a lead WORD for the string length. I thought it was silly when you want your load/store code to match 1-to-1 but you have to add an extra line when storing a string to write a newline :rolleyes: Mark
"Posting a VB.NET question in the C++ forum will end in tears." Chris Maunder