MFC文件操作
1.相关类
CFile类 封装了文件句柄以及相关操作的API
CFileFind类 封装了文件查找相关的类
2 CFile类的使用
2.1打开或者创建文件
2.2文件读写 通常放到宜昌处理结果中
2.3关闭文件
CFileFind
查找指定目录下的所有文件和文件夹
开始查找
virtual BOOL FindFile( LPCTSTR pstrName = NULL, DWORD dwUnused = 0 );
查找下一个文件
virtual BOOL FindNextFile( );
GetXXX 或者 IsXXX,获取文件信息并判断。
CFileFind::Close ,结束查找
序列化(串行化)
方便文件读写,避免类型转换
将数据以二进制流的方式保存到文件,或者重文件读取.
相关类
CFile
CArchive 归档类,执行具体的数据读写操作。使用该类替换CFile类的Read,Write函数
写操作“<<”
读操作“>>”
序列化的操作步骤
CFile::Open
定义CArchive类的对象
>>或<<,执行读写操作
关闭CArchive对象
CFile::Close()
对象的序列化。
将对象的所有数据以二进制流写入文件。
反序列化 从文件先读取类的信息,创建对象,然后读取对象的成员初始化新创建的对象。
对象的序列化以动态创建为必要条件。
定义一个支持序列化的类。
必须是CObject的子类
添加序列化的声明宏和实现宏
重写Serialize函数,在函数中序列化对象的成员。
1,_init_Cstudent 结构体变量,作用是调用AfxClassInfo
在函数中,获取应用程序的模块信息,将CStudent的运行时信息的地址保存到m_classList链表
中(m_classList是模块状态信息的成员)。
2,operator>> 友元函数加载CStudent类的对象
对象序列化过程。
序列化
调用ar.WriteObject()函数
在函数中,首先调用GetRuntimeClass函数获取CStudent类的运行时信息。
调用WriteClass函数,将类的信息写入到文件.
在store函数中依次将类的,版本,长度,名称 写入文件。
调用Serialize函数,函数中依次将CStudent类的成员变量写入到文件。
反序列化
ar.ReadObject
ReadClass->Load
Serialize
函数跟踪 _AFX_INLINE CArchive& AFXAPI operator<<(CArchive& ar, const CObject* pOb) { ar.WriteObject(pOb); return ar; } void CArchive::WriteObject(const CObject* pOb) { // object can be NULL ASSERT(IsStoring()); // proper direction DWORD nObIndex; ASSERT(sizeof(nObIndex) == 4); ASSERT(sizeof(wNullTag) == 2); ASSERT(sizeof(wBigObjectTag) == 2); ASSERT(sizeof(wNewClassTag) == 2); // make sure m_pStoreMap is initialized MapObject(NULL); if (pOb == NULL) { // save out null tag to represent NULL pointer *this << wNullTag; } else if ((nObIndex = (DWORD)(*m_pStoreMap)[(void*)pOb]) != 0) // assumes initialized to 0 map { // save out index of already stored object if (nObIndex < wBigObjectTag) *this << (WORD)nObIndex; else { *this << wBigObjectTag; *this << nObIndex; } } else { // write class of object first CRuntimeClass* pClassRef = pOb->GetRuntimeClass(); WriteClass(pClassRef); // enter in stored object table, checking for overflow CheckCount(); (*m_pStoreMap)[(void*)pOb] = (void*)m_nMapCount++; // cause the object to serialize itself ((CObject*)pOb)->Serialize(*this); } } void CArchive::CheckCount() { if (m_nMapCount >= nMaxMapCount) AfxThrowArchiveException(CArchiveException::badIndex, m_strFileName); } _AFX_INLINE CArchive& CArchive::operator<<(WORD w) { if (m_lpBufCur + sizeof(WORD) > m_lpBufMax) Flush(); void CRuntimeClass::Store(CArchive& ar) const // stores a runtime class description { WORD nLen = (WORD)lstrlenA(m_lpszClassName); ar << (WORD)m_wSchema << nLen; ar.Write(m_lpszClassName, nLen*sizeof(char)); } CRuntimeClass* CObject::GetRuntimeClass() const { return RUNTIME_CLASS(CObject); } void CArchive::WriteClass(const CRuntimeClass* pClassRef) { ASSERT(pClassRef != NULL); ASSERT(IsStoring()); // proper direction if (pClassRef->m_wSchema == 0xFFFF) { TRACE1("Warning: Cannot call WriteClass/WriteObject for %hs.\n", pClassRef->m_lpszClassName); AfxThrowNotSupportedException(); } // make sure m_pStoreMap is initialized MapObject(NULL); // write out class id of pOb, with high bit set to indicate // new object follows // ASSUME: initialized to 0 map DWORD nClassIndex; if ((nClassIndex = (DWORD)(*m_pStoreMap)[(void*)pClassRef]) != 0) { // previously seen class, write out the index tagged by high bit if (nClassIndex < wBigObjectTag) *this << (WORD)(wClassTag | nClassIndex); else { *this << wBigObjectTag; *this << (dwBigClassTag | nClassIndex); } } else { // store new class *this << wNewClassTag; pClassRef->Store(*this); // store new class reference in map, checking for overflow CheckCount(); (*m_pStoreMap)[(void*)pClassRef] = (void*)m_nMapCount++; } } #define DECLARE_SERIAL(class_name) _DECLARE_DYNCREATE(class_name) AFX_API friend CArchive& AFXAPI operator>>(CArchive& ar, class_name* &pOb); #define IMPLEMENT_SERIAL(class_name, base_class_name, wSchema) CObject* PASCAL class_name::CreateObject() { return new class_name; } _IMPLEMENT_RUNTIMECLASS(class_name, base_class_name, wSchema, class_name::CreateObject) AFX_CLASSINIT _init_##class_name(RUNTIME_CLASS(class_name)); CArchive& AFXAPI operator>>(CArchive& ar, class_name* &pOb) { pOb = (class_name*) ar.ReadObject(RUNTIME_CLASS(class_name)); return ar; } struct CFileStatus { CTime m_ctime; // creation date/time of file CTime m_mtime; // last modification date/time of file CTime m_atime; // last access date/time of file LONG m_size; // logical size of file in bytes BYTE m_attribute; // logical OR of CFile::Attribute enum values BYTE _m_padding; // pad the structure to a WORD TCHAR m_szFullName[_MAX_PATH]; // absolute path name #ifdef _DEBUG void Dump(CDumpContext& dc) const; #endif }; class CTimeSpan { public: // Constructors CTimeSpan(); CTimeSpan(time_t time); CTimeSpan(LONG lDays, int nHours, int nMins, int nSecs); CTimeSpan(const CTimeSpan& timeSpanSrc); const CTimeSpan& operator=(const CTimeSpan& timeSpanSrc); // Attributes // extract parts LONG GetDays() const; // total # of days LONG GetTotalHours() const; int GetHours() const; LONG GetTotalMinutes() const; int GetMinutes() const; LONG GetTotalSeconds() const; int GetSeconds() const; // Operations // time math CTimeSpan operator-(CTimeSpan timeSpan) const; CTimeSpan operator+(CTimeSpan timeSpan) const; const CTimeSpan& operator+=(CTimeSpan timeSpan); const CTimeSpan& operator-=(CTimeSpan timeSpan); BOOL operator==(CTimeSpan timeSpan) const; BOOL operator!=(CTimeSpan timeSpan) const; BOOL operator<(CTimeSpan timeSpan) const; BOOL operator>(CTimeSpan timeSpan) const; BOOL operator<=(CTimeSpan timeSpan) const; BOOL operator>=(CTimeSpan timeSpan) const; #ifdef _UNICODE // for compatibility with MFC 3.x CString Format(LPCSTR pFormat) const; #endif CString Format(LPCTSTR pFormat) const; CString Format(UINT nID) const; // serialization #ifdef _DEBUG friend CDumpContext& AFXAPI operator<<(CDumpContext& dc,CTimeSpan timeSpan); #endif friend CArchive& AFXAPI operator<<(CArchive& ar, CTimeSpan timeSpan); friend CArchive& AFXAPI operator>>(CArchive& ar, CTimeSpan& rtimeSpan); private: time_t m_timeSpan; friend class CTime; }; class CFile : public CObject { DECLARE_DYNAMIC(CFile) public: // Flag values enum OpenFlags { modeRead = 0x0000, modeWrite = 0x0001, modeReadWrite = 0x0002, shareCompat = 0x0000, shareExclusive = 0x0010, shareDenyWrite = 0x0020, shareDenyRead = 0x0030, shareDenyNone = 0x0040, modeNoInherit = 0x0080, modeCreate = 0x1000, modeNoTruncate = 0x2000, typeText = 0x4000, // typeText and typeBinary are used in typeBinary = (int)0x8000 // derived classes only }; enum Attribute { normal = 0x00, readOnly = 0x01, hidden = 0x02, system = 0x04, volume = 0x08, directory = 0x10, archive = 0x20 }; enum SeekPosition { begin = 0x0, current = 0x1, end = 0x2 }; enum { hFileNull = -1 }; // Constructors CFile(); CFile(int hFile); CFile(LPCTSTR lpszFileName, UINT nOpenFlags); // Attributes UINT m_hFile; operator HFILE() const; virtual DWORD GetPosition() const; BOOL GetStatus(CFileStatus& rStatus) const; virtual CString GetFileName() const; virtual CString GetFileTitle() const; virtual CString GetFilePath() const; virtual void SetFilePath(LPCTSTR lpszNewName); // Operations virtual BOOL Open(LPCTSTR lpszFileName, UINT nOpenFlags, CFileException* pError = NULL); static void PASCAL Rename(LPCTSTR lpszOldName, LPCTSTR lpszNewName); static void PASCAL Remove(LPCTSTR lpszFileName); static BOOL PASCAL GetStatus(LPCTSTR lpszFileName, CFileStatus& rStatus); static void PASCAL SetStatus(LPCTSTR lpszFileName, const CFileStatus& status); DWORD SeekToEnd(); void SeekToBegin(); // backward compatible ReadHuge and WriteHuge DWORD ReadHuge(void* lpBuffer, DWORD dwCount); void WriteHuge(const void* lpBuffer, DWORD dwCount); // Overridables virtual CFile* Duplicate() const; virtual LONG Seek(LONG lOff, UINT nFrom); virtual void SetLength(DWORD dwNewLen); virtual DWORD GetLength() const; virtual UINT Read(void* lpBuf, UINT nCount); virtual void Write(const void* lpBuf, UINT nCount); virtual void LockRange(DWORD dwPos, DWORD dwCount); virtual void UnlockRange(DWORD dwPos, DWORD dwCount); virtual void Abort(); virtual void Flush(); virtual void Close(); // Implementation public: virtual ~CFile(); #ifdef _DEBUG virtual void AssertValid() const; virtual void Dump(CDumpContext& dc) const; #endif enum BufferCommand { bufferRead, bufferWrite, bufferCommit, bufferCheck }; virtual UINT GetBufferPtr(UINT nCommand, UINT nCount = 0, void** ppBufStart = NULL, void** ppBufMax = NULL); protected: BOOL m_bCloseOnDelete; CString m_strFileName; }; class CArchive { public: // Flag values enum Mode { store = 0, load = 1, bNoFlushOnDelete = 2, bNoByteSwap = 4 }; CArchive(CFile* pFile, UINT nMode, int nBufSize = 4096, void* lpBuf = NULL); ~CArchive(); // Attributes BOOL IsLoading() const; BOOL IsStoring() const; BOOL IsByteSwapping() const; BOOL IsBufferEmpty() const; CFile* GetFile() const; UINT GetObjectSchema(); // only valid when reading a CObject* void SetObjectSchema(UINT nSchema); // pointer to document being serialized -- must set to serialize // COleClientItems in a document! CDocument* m_pDocument; // Operations UINT Read(void* lpBuf, UINT nMax); void Write(const void* lpBuf, UINT nMax); void Flush(); void Close(); void Abort(); // close and shutdown without exceptions // reading and writing strings void WriteString(LPCTSTR lpsz); LPTSTR ReadString(LPTSTR lpsz, UINT nMax); BOOL ReadString(CString& rString); public: // Object I/O is pointer based to avoid added construction overhead. // Use the Serialize member function directly for embedded objects. friend CArchive& AFXAPI operator<<(CArchive& ar, const CObject* pOb); friend CArchive& AFXAPI operator>>(CArchive& ar, CObject*& pOb); friend CArchive& AFXAPI operator>>(CArchive& ar, const CObject*& pOb); // insertion operations CArchive& operator<<(BYTE by); CArchive& operator<<(WORD w); CArchive& operator<<(LONG l); CArchive& operator<<(DWORD dw); CArchive& operator<<(float f); CArchive& operator<<(double d); CArchive& operator<<(int i); CArchive& operator<<(short w); CArchive& operator<<(char ch); CArchive& operator<<(unsigned u); // extraction operations CArchive& operator>>(BYTE& by); CArchive& operator>>(WORD& w); CArchive& operator>>(DWORD& dw); CArchive& operator>>(LONG& l); CArchive& operator>>(float& f); CArchive& operator>>(double& d); CArchive& operator>>(int& i); CArchive& operator>>(short& w); CArchive& operator>>(char& ch); CArchive& operator>>(unsigned& u); // object read/write CObject* ReadObject(const CRuntimeClass* pClass); void WriteObject(const CObject* pOb); // advanced object mapping (used for forced references) void MapObject(const CObject* pOb); // advanced versioning support void WriteClass(const CRuntimeClass* pClassRef); CRuntimeClass* ReadClass(const CRuntimeClass* pClassRefRequested = NULL, UINT* pSchema = NULL, DWORD* pObTag = NULL); void SerializeClass(const CRuntimeClass* pClassRef); // advanced operations (used when storing/loading many objects) void SetStoreParams(UINT nHashSize = 2053, UINT nBlockSize = 128); void SetLoadParams(UINT nGrowBy = 1024); // Implementation public: BOOL m_bForceFlat; // for COleClientItem implementation (default TRUE) BOOL m_bDirectBuffer; // TRUE if m_pFile supports direct buffering void FillBuffer(UINT nBytesNeeded); void CheckCount(); // throw exception if m_nMapCount is too large // special functions for reading and writing (16-bit compatible) counts DWORD ReadCount(); void WriteCount(DWORD dwCount); // public for advanced use UINT m_nObjectSchema; CString m_strFileName; protected: // archive objects cannot be copied or assigned CArchive(const CArchive& arSrc); void operator=(const CArchive& arSrc); BOOL m_nMode; BOOL m_bUserBuf; int m_nBufSize; CFile* m_pFile; BYTE* m_lpBufCur; BYTE* m_lpBufMax; BYTE* m_lpBufStart; // array/map for CObject* and CRuntimeClass* load/store UINT m_nMapCount; union { CPtrArray* m_pLoadArray; CMapPtrToPtr* m_pStoreMap; }; // map to keep track of mismatched schemas CMapPtrToPtr* m_pSchemaMap; // advanced parameters (controls performance with large archives) UINT m_nGrowSize; UINT m_nHashSize; };
源代码
// MFCSerial.cpp : Defines the entry point for the console application. // #include "stdafx.h" void Store(){ CFile file; if(!file.Open("c:/Serial.dat",CFile::modeCreate|CFile::modeWrite)){ printf("文件打开失败"); return ; } CArchive archive(&file,CArchive::store); archive<<100<<12.25<<"Hello CArchive"; archive.Close(); file.Close(); } void Load(){ CFile file; if(!file.Open("c:/Serial.dat",CFile::modeRead)){ printf("文件读取失败!"); return ; } CArchive ar(&file,CArchive::load); int num=0; double dou=0.0; CString cStr; ar>>num>>dou>>cStr; printf("%d,%lf,%s\n",num,dou,cStr); ar.Close(); file.Close(); } void CFileSerial(){ } int main(int argc, char* argv[]) { // Store(); Load(); return 0; }
// MFCObjectSerial.cpp : Defines the entry point for the console application. // #include "stdafx.h" class CStudent:public CObject{ public: CStudent(); CStudent(CString m_sName,UINT m_iAge); virtual void Serialize(CArchive& ar); void Show(); public: CString m_sName; UINT m_iAge; //DECLARE_SERIAL(CStudent) _DECLARE_DYNCREATE(CStudent) AFX_API friend CArchive& AFXAPI operator>> (CArchive& ar, CStudent* &pOb); }; // // // IMPLEMENT_SERIAL(CStudent,CObject,1) // CObject* PASCAL CStudent::CreateObject(){ return new CStudent; } // _IMPLEMENT_RUNTIMECLASS(CStudent, CObject, 1, CStudent::CreateObject) AFX_DATADEF CRuntimeClass CStudent::classCStudent = { "CStudent", sizeof(class CStudent), 1, CStudent::CreateObject, RUNTIME_CLASS(CObject), NULL }; CRuntimeClass* CStudent::GetRuntimeClass() const { return RUNTIME_CLASS(CStudent); } AFX_CLASSINIT _init_CStudent(RUNTIME_CLASS(CStudent)); CArchive& AFXAPI operator>>(CArchive& ar, CStudent* &pOb){ pOb = (CStudent*) ar.ReadObject(RUNTIME_CLASS(CStudent)); return ar; } // CStudent::CStudent(){} CStudent::CStudent(CString m_sName,UINT m_iAge){ this->m_sName=m_sName; this->m_iAge=m_iAge; } void CStudent::Serialize(CArchive& ar){ CObject::Serialize(ar); if(ar.IsStoring()){ ar<<m_sName<<m_iAge; }else{ ar>>m_sName>>m_iAge; } } void CStudent::Show(){ printf("学生姓名:%s\n学生年龄:%d\n",m_sName,m_iAge); } // void ObjStore(CStudent &stu){ CFile file; if(!file.Open("c:/stu.dat",CFile::modeCreate|CFile::modeReadWrite)){ printf("文件创建失败!\n"); return; } CArchive ar(&file,CArchive::store); ar<<&stu; ar.Close(); file.Close(); } void ObjLoad(){ CFile file; if(!file.Open("c:/stu.dat",CFile::modeRead)){ printf("文件打开失败!\n"); return ; } CArchive ar(&file,CArchive::load); CStudent *stu=NULL; ar>>stu; //封装反序列化全部过程 ar.Close(); file.Close(); if(stu){ stu->Show(); } } int main(int argc, char* argv[]) { CStudent stu("aaa",20); // ObjStore(stu); ObjLoad(); return 0; }