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

  • On-demand Event Event Date: December 18, 2014 The Internet of Things (IoT) incorporates physical devices into business processes using predictive analytics. While it relies heavily on existing Internet technologies, it differs by including physical devices, specialized protocols, physical analytics, and a unique partner network. To capture the real business value of IoT, the industry must move beyond customized projects to general patterns and platforms. Check out this webcast and join industry experts as …

  • Today's agile organizations pose operations teams with a tremendous challenge: to deploy new releases to production immediately after development and testing is completed. To ensure that applications are deployed successfully, an automatic and transparent process is required. We refer to this process as Zero Touch Deployment™. This white paper reviews two approaches to Zero Touch Deployment--a script-based solution and a release automation platform. The article discusses how each can solve the key …

Most Popular Programming Stories

More for Developers

RSS Feeds