250 likes | 260 Views
Learn how to save and load data from files using CFile class and Serialization in C++ programming. Understand file opening, closing, reading, and writing operations. Explore basics, serializable types, and versioning of serializable classes.
E N D
File I/O and Serialization Jim Fawcett CSE791 – Advanced Windows Programming Summer 2002
Topics Two ways to support document saving and loading • CFile Class Call CFile class member functions to write data to disk and read it back • Serialization CArchive Class associated with CFile Class
CFile::Open CFile::Close CFile::Read CFile::Write CFile::Rename CFile::Remove CFile::GetFileName CFile::GetFileTitle CFile::GetFilePath CFile::SetFilePath CFile Class
Opening Files • Construct an CFile object and call CFile:: Open CFile file; CFileException e; if(file.Open(_T(“File.txt”), CFile::modeReadWrite, &e)){ // worked! } else{ // Open failed. Tell the user why e.ReportError(); }
Opening Files • Call CFile’s constructor to open the file try { CFile file(_T(“File.txt”), CFile::modeReadWrite); ……. } catch (CFileException* e){ e->ReportError(); e->Delete(); }
Creating Files • Include CFile::modeCreate flag in the CFile::Open() or in the CFile constructor CFile file(_T(“File.txt”), CFile::modeReadWrite| CFile::modeCreate|CFile::modeNoTruncate);
Closing Files • Call CFile::Close() explicitly CFile file(_T(“File.txt”), CFile::modeReadWrite); //……….. file.Close(); • Let CFile’s destructor close the file CFile file(_T(“File.txt”), CFile::modeReadWrite); //………. } // destructor called when Cfile object goes out of scope
Reading and Writing Files • CFile::Read CFile file; // ….. UINT nBytesRead = file.Read( pbuf, lstrlen(pbuf)); • CFile::Write CFile file; //….. file.Write(sz, lstrlen(sz));
Serialization • The basic idea of serialization is that an object should be able to write it’s current state to persistent storage and later, it can be re_created by reading it’s state from the storage. • Serialization Basics Without Serialization CFile file(_T(“File.txt”), CFile::modeReadWrite); file.Write (&a, sizeof (a)); file.Write(&b, sizeof (b));
Serialization • Serialization basics with Serialization
Serialization • Writing files CArchive ar(&file, CArchive::store); ar<<a<<b; • Reading files CArchive ar(&file, CArchive::load); ar>>a>>b;
Serializable types • Primitive types BYTEs, WORDs, LONGs, DWORDs, floats, doubles, ints, unsigned ints, shorts and chars • Nonprimitive data types represented by MFC classes MFC overrides the<< and >> operators so that nonprimitive types can be serialized to and from archive: CString, CTime, CTimeSpan, CSize, CPoint and Crect
How to Write Serializable Classes • Derive classes from CObject, either directly or indirectly • Include MFC’s DECLARE_SERIAL macro in the class declaration, with class’s name as parameter • Override the base class’s serialize function • If the derived class doesn’t have a default constructor, add one • Include MFC’s IMPLEMENT_SERIAL macro in the class implementation. It takes three parameters: the class name, the name of the base class and a schema number
Example: writing serializable class class CMyclass : public CObject{ DECLARE_SERIAL (CMyclass) protected: int m_a; int m_b; public: CMyclass(){} // Required! CMyclass (int a, int b) {m_a = a; m_b = b;} int sum (){return (m_a + m_b);} void Serialize (CArchive& ar); };
Example The Serializefunction looks like this: void CMyclass::Serialize(CArchive &ar) { CObject::Serialize (ar); if (ar.IsStoring()) ar<<m_a<<m_b; if (ar.IsLoading()) ar>>m_a>>m_b; }
Example Add this statement in class implementation IMPLEMENT_SERIAL ( CMyclass, CObject, 1)
Note: • MFC overloads CArchive’s insertion and extraction operators for CObject pointer, but not for Cobjects • This will work CMyclass* pMyclass = new CMyclass(2, 3); ar << pMyclass; • This will not work CMyclass Myclass (2, 3); ar << Myclass;
Versioning Serializable Classes:Versionable Schemas • New version can read older versions • Versionable schema a schema number that includes a VERSIONABLE_SCHEMA flag IMPLEMENT_SERIAL ( CMyclass, CObject, 2 | VERSIONABLE_SCHEMA )
How to Write Versioning SerializableClasses (new version class declaration) • ADD new data member to the class class CMyclass:public CObject{ DECLARE_SERIAL (CMyclass) protected: int m_a; int m_b; int m_c; // add new persistent data member public: CMyclass(){} CMyclass (int a, int b, int c) {m_a = a; m_b = b;m_c=c;} // --- };
How to Write Versioning SerializableClasses • OR the value VERSIONABLE_SCHEMA into the schema number in the IMPLEMENT_SERIAL macro Original: IMPLEMENT_SERIAL ( CMyclass, CObject, 1) Revised: IMPLEMENT_SERIAL ( CMyclass, CObject, 2| VERSIONABLE_SCHEMA )
(continued) • Modify the class’s Serialize function: void CMyclass::Serialize(CArchive &ar){ CObject::Serialize (ar); if (ar.IsStoring()) ar<<m_a<<m_b<<m_c; if (ar.IsLoading()) { UINT nSchema = ar.GetObjectSchema(); switch (nSchema) { // continued on next slide
continue case 1: // Version 1 ar >> m_a >> m_b; m_c = 0; //default value break; case 2: // Version 2 ar >> m_a >> m_b >> m_c; break; default: //Unknown version AfxThrowArchiveException (CArchiveException::badSchema); break; } } }