Serializable CListCtrl with check sum verify

More questions on Discussion board are based on store/load a list control to file. One way to serialize the list control is to save information about the header of list control, and then serialize all items from list control. The idea is to open a file in CFile::modeCreate or CFile::modeRead depending on kind of operation, store or load the list control. Then we will create a archive object from this file to easily store/load the objects. For more security this method has implemented a check sum of file.

Storing information in file.

First we will save a signature, as sample I chose this to be 'ListCtrl - ObjectStore', for a short check of file type. Then we will store a double word where at the end of the storing operation we will put the calculated check sum. After that, each column in stored, and finished with a -1 value to limit the definitions of columns in file.

Loading information from file.

Read signature. If this is what I stored, then I get the check sum from file, to verify with check sum of file. If all these are right,the loading continues as with the storing procedure.

The implementation contain a class CCheckArchive, and function Serialize. The CCheckArchive class has some virtual functions overridable ( like operator <<, used in Serialize functions) to complete the check sum.

For more detail, I invite the user to see the code. For store/load list control the user can call the function ::Serialize, with the folowing arguments. First is the destinatin list control, the second is the file name, and the last argument is the required operation; TRUE for storing, FALSE for loading. I think that the function Serialize and CCheckArchive, can be easly extended. Any kind of help, or information I will receive/send with pleasure.

Sincerely, Mihai Filimon

class CCheckArchive : public CArchive
{
	DWORD m_wCheckSum;
protected:

	// Function name : Sum
	// Description   : Add every byte from wData
	// Return type   : static DWORD
	// Argument      : DWORD wData
	static DWORD Sum(DWORD wData)
	{
		return HIBYTE(HIWORD(wData)) + LOBYTE(HIWORD(wData)) +
				HIBYTE(LOWORD(wData)) + LOBYTE(LOWORD(wData));
	};

public:

	// Function name : CCheckArchive
	// Description   : Contructor uses in Serialize() function
	// Return type   :
	// Argument      : CFile* pFile
	// Argument      : UINT nMode
	CCheckArchive(CFile* pFile, UINT nMode) : CArchive( pFile, nMode, 4096, NULL )
	{
		m_wCheckSum = 0;
	}

	// Function name : ~CCheckArchive
	// Description   : Destructor
	// Return type   : virtual
	virtual ~CCheckArchive() {};

	// Function name : operator <<
	// Description   : This operator is call in Serialize function. Add
	//				   every byte write in file, in m_wCheckSum
	// Return type   : virtual CArchive&
	// Argument      : DWORD wData
	virtual CArchive& operator << (DWORD wData)
	{
		m_wCheckSum += Sum(wData);
		return ((CArchive&)*this) << wData;
	}

	// Function name : operator <<
	// Description   : This operator is call in Serialize function. Add
	//				   every byte write in file, in m_wCheckSum
	// Return type   : virtual CArchive&
	// Argument      : CString& sData
	virtual CArchive& operator << (CString& sData)
	{
		LPTSTR lpszS = (LPTSTR)(LPCTSTR)sData;

		while (*lpszS)
		m_wCheckSum += BYTE(*lpszS++);
		m_wCheckSum += Sum(sData.GetLength());
		return ((CArchive&)*this) << sData;
	}

	// Function name : GetCheckSum
	// Description   : Return the calculated check sum
	// Return type   : DWORD
	DWORD GetCheckSum()
	{
		return m_wCheckSum;
	};

	// Function name : GetLastPosition
	// Description   : Called for found the position of file in write
	//				   operation
	// Return type   : DWORD
	DWORD GetLastPosition()
	{
		return m_lpBufCur - m_lpBufStart;
	};

	// Function name : Verify
	// Description   : Check if chkSum verify the file, that must be in
	//				   loading
	// Return type   : BOOL
	// Argument      : DWORD chkSum
	BOOL Verify(DWORD chkSum)
	{
		static const max = 2048;
		DWORD w = 0;
		ASSERT (IsLoading());
		TRY
		{
			CFile* pFile = GetFile();
			DWORD bookmark = pFile->GetPosition();
			pFile->SeekToBegin();
			BYTE buffer[max], *pBuffer = NULL;
			int nRead = 0;
			while (nRead = pFile->Read(&buffer, max))
			{
				pBuffer = buffer;
				for (int i = 0; i < nRead; i++, w += *pBuffer++);
			}
			w -= Sum(chkSum);
			pFile->Seek(bookmark, CFile::begin);
		}
		CATCH_ALL(e)
		{
			return FALSE;
		}
		END_CATCH_ALL;
		return w == chkSum;
	}
};

// Function name : Serialize
// Description   : Call this function to store/load a list control
// Return type   : BOOL
// Argument      : CListCtrl* pListCtrl
// Argument      : LPCTSTR lpszFileName
// Argument      : BOOL bStoring = TRUE
BOOL Serialize(CListCtrl* pListCtrl, LPCTSTR lpszFileName, BOOL bStoring = TRUE)
{
	static const TCHAR* lpszSignature = _T("ListCtrl - StoreObject");
	CFile file;
	if (file.Open(lpszFileName, bStoring ? CFile::modeWrite | CFile::modeCreate: CFile::modeRead))
	TRY
	{
		CString s; CCheckArchive ar(&file, bStoring ? CArchive::store :CArchive::load);
		DWORD chkSum = 0;
		if (bStoring)
		{
			ar << CString(lpszSignature);
			DWORD sC = ar.GetLastPosition();
			ar << chkSum;
			LV_COLUMN column; TCHAR buffer[MAX_PATH]; int i = NULL, nColumn = 0;

			column.mask = LVCF_FMT | LVCF_TEXT | LVCF_WIDTH;
			column.pszText = buffer;
			column.cchTextMax = MAX_PATH;
			for (i = 0; pListCtrl->GetColumn(i, &column); i++, nColumn++)
			{
				ar << column.fmt;
				ar << column.cx;
				ar << CString(column.pszText);
			}
			ar << UINT(-1);
			int n = pListCtrl->GetItemCount();
			ar << n;
			for (i = 0; i < n; i++)
			{
				for (int j = 0; j < nColumn; j++)
				ar << pListCtrl->GetItemText(i, j);
				ar << pListCtrl->GetItemData(i);
			}
			ar.Flush();
			ar.GetFile()->Seek(sC,CFile::begin);
			chkSum = ar.GetCheckSum();
			ar.GetFile()->Write(&chkSum, sizeof(chkSum));
		}
		else
		{
			ar >> s;
			if (s.Compare(lpszSignature) == 0)
			{
				ar >> chkSum;
				if (ar.Verify(chkSum))
				{
					CString text;
					text.Format(_T("%i"),chkSum);
					AfxMessageBox(text);
					LV_COLUMN column; TCHAR buffer[MAX_PATH]; int i = NULL, nColumn = 0;
					column.mask = LVCF_FMT | LVCF_TEXT | LVCF_WIDTH;
					column.pszText = buffer;
					column.cchTextMax = MAX_PATH;
					for (; TRUE; nColumn++)
					{
						ar >> column.fmt;
						if (column.fmt < 0) break;
						ar >> column.cx;
						ar >> s;
						column.pszText = (LPTSTR)(LPCTSTR)s;
						pListCtrl->InsertColumn(nColumn, &column);
					}
					int n = NULL;
					ar >> n;
					for (i = 0; i < n; i++)
					{
						int nItem = pListCtrl->InsertItem(i, _T(""));
						for (int j = 0; j < nColumn; j++)
						{
							ar >> s;
							pListCtrl->SetItemText(nItem, j, s);
						}
						DWORD wData;
						ar >> wData;
						pListCtrl->SetItemData(nItem, wData);
					}
				}
			}
		}
		ar.Close();
		file.Close();
	}
	CATCH_ALL(e)
	{
		return FALSE;
	}
	END_CATCH_ALL
	return TRUE;
}

Last updated: 29 July 1998 by Rob Osborne



Comments

  • Try CExtReport

    Posted by Legacy on 08/18/2003 12:00am

    Originally posted by: marcus gesing

    Source and demo:
    http://home.arcor.de/footwear-box/various/coding/ExtLib.zip

    Reply
  • I need help using the mfc serialize funktion width your code

    Posted by Legacy on 05/12/2000 12:00am

    Originally posted by: Andreas H

    I have to tell you this cameas a dream. I m at the moment
    involved in my first project involving serializing data to and from files.
    However as you might have guest im not that good in programming vc++.
    Ive only been doing this for 5 months and im learning not only by books
    but also from taking codes from codeguru.com for use in my applications.
    Unfortunatly i dont quite understand your code posted there.
    Because instead of using a new class i want to used the MFC serialize function.
    I tried to modify it without any bigger succes, since i didnt really know
    where to put the checksum finctions and so on. So i was kind of hoping for
    that you could help me out. I would really appreciate the help.
    In my project I have a listview cointaing data in 2 cols and a unspecified
    number of rows. I also have 2 edit boxes containing 3 strings of text.
    I need al this serialized into the file.
    The name of the variables:
    CListCtrl = m_lstSourceFiles
    Editbox1 = m_strFolder
    Editbox2 = m_strContent
    Editbox3 = m_strName
    Please help me modify the code for my needs and be detailed in your
    explanations so that i can learn it.

    Thank you

    Reply
Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • Java developers know that testing code changes can be a huge pain, and waiting for an application to redeploy after a code fix can take an eternity. Wouldn't it be great if you could see your code changes immediately, fine-tune, debug, explore and deploy code without waiting for ages? In this white paper, find out how that's possible with a Java plugin that drastically changes the way you develop, test and run Java applications. Discover the advantages of this plugin, and the changes you can expect to see …

  • As more and more organizations migrate to the cloud, many are faced with hidden costs emerging from unexpected places. Two non-obvious and non-trivial factors can drive up costs. First are separate charges for everything from server memory to intrusion detection. Second are the high personnel costs for early-generation, manually operated clouds. These costs can rack up quickly, creating total cost of ownership (TCO) surprises. Keeping TCO low in the cloud is essentially a matter of management strategy. IT …

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds