CTypedPtrMap模板指针类的用法 和CArchive类

在编程中运用CTypedPtrMap指针模板类的方法,其存储结构占用物理空间小,比单纯的用数组结构存储的文件将小很多,所以是一种非常推荐的存储及读取文件的方法。

你必须在stdafx.h文件中 包含 #include <afxtempl.h>    // MFC templates
在头文件中包含 #include <io.h>

其中 CBank.h文件如下:

class CBank : public CObject  
{
DECLARE_SERIAL(CBank)   //声明序列化存储
public:
       CBank();
       CBank(CString str){ m_bankname = str; }
       CBank(const CBank &b){ m_bankname= b.m_bankname;} //拷贝构造函数
      virtual ~CBank();
private:
       CString m_bankname;
public:
    virtual void Serialize(CArchive& ar);
};

 

typedef CTypedPtrMap<CMapStringToOb,

                     CString,

                     CBank*>CBanktmp; //这个才是我们根据此类生成的类型

它的实现文件.cpp如下:

IMPLEMENT_SERIAL(CBank, CObject, 1)     //实现序列化存储
CBank::CBank()
{
m_bankname="";
}
CBank::~CBank()
{

 

}
void CBank::Serialize(CArchive& ar)
{
    if (ar.IsLoading())
    {
        ar >> m_bankname;
    }
    else
    {
        ar << m_bankname;
    }
}

/*----------------------------------------------------
从文件中读取参数:
注意: 其中的m_map是这样定义的:CBanktmp m_map;
-------------------------------------------------*/

void CDlgBankIn::LoadBankName()
{
       UINT nFlags = CFile::typeBinary |CFile::modeReadWrite;
       if(_access(_T("BankName.dat"),0))
       {
              nFlags |= CFile::modeCreate;
       }
       CFile file;
       CFileException fe;
       if (file.Open(_T("BankName.dat"),nFlags, &fe))
       {
           if(file.GetLength()==0)   //如果文件为空则不进行读取操作
           {
           }
           else
           {
                CArchive ar(&file, CArchive::load);
                m_map.Serialize(ar);   //读取文件
               //根据文件内容填充列表框
                POSITION   pos;
                CString    strKey;
                CBank   *pB=NULL;
                for( pos = m_map.GetStartPosition(); pos != NULL; )
                {
                    m_map.GetNextAssoc(pos,strKey,(CBank*)pB);
                    m_CmbBank.AddString(strKey);
                }
                delete pB;
              }
       }
       file.Close();
}

 

/*-------------------------------------------------
功能: 先打开文件,然后查找文件中是否有与编辑框关键字相同的内容,
       如果有相同内容则不添加,如果没有相同内容则写文件.
------------------------------------- ------------*/

void CDlgBankList::OnBtnAdd() 
{
       // TODO: Add your control notification handler code here
       CString strKey;
       GetDlgItemText(IDC_EDITBank,strKey);
       if (0 != strKey.GetLength())
       {
          CBank *pB;
          //打开文件
         UINT nFlags = CFile::typeBinary |CFile::modeRead;
          CFile file;
          CFileException fe;
          if (file.Open(_T("BankName.dat"),nFlags, &fe))
          {
                 if(file.GetLength()==0) //如果文件为空则不进行序列化操作
                 {

 

                 }
                 else
                 {
                  CArchive ar(&file, CArchive::load);
                  m_map.Serialize(ar);
                 }
               //分析文件并给文件添加编辑框的内容
                if(!m_map.Lookup(strKey,(CBank*)pB)) //当不存在时才需要添加
                  {
                      if (CB_ERR != m_ListBox.AddString(strKey))
                      {
                         m_map.SetAt(strKey, new CBank(strKey)); //给关键字strKey赋值
                      }
                 }
          }
       file.Close();

       //存储文件
     nFlags = CFile::typeBinary |CFile::modeWrite;
       if (file.Open(_T("BankName.dat"),nFlags, &fe))
       {
            CArchive ar(&file, CArchive::store);
            m_map.Serialize(ar);   //序列化存储
     }
    }
}

/*-------------------------------------------------
功能: 先打开文件,然后查找文件中的关键字,
     找到后则删除此关键字, 但是注意关键字对应的内容仍然没有删除,这点期待改进.
-------------------------------------------------*/

void CDlgBankList::OnBtnDel() 
{
       // TODO: Add your control notification handler code here
       int iIndex;      
       CString strKey;
       if(LB_ERR!=m_ListBox.GetCurSel())
       {
        //打开文件
      & nbsp;     UINT nFlags = CFile::typeBinary |CFile::modeRead;
           CFile file;
           CFileException fe;
           if (file.Open(_T("BankName.dat"),nFlags, &fe))
           {
              CArchive ar(&file, CArchive::load);
              m_map.Serialize(ar);
              iIndex=m_ListBox.GetCurSel();
              m_ListBox.GetText(iIndex,strKey);
              m_ListBox.DeleteString(iIndex);
              //分析文件并给文件添加编辑框的内容
               CBank *pB=NULL;
              if(m_map.Lookup(strKey,(CBank*)pB))
              {
                  m_map.RemoveKey(strKey);   //删除关键字,但没有删除关键字对应的内容
               }
            }
            file.Close();
            //存储文件
           nFlags = CFile::typeBinary |CFile::modeWrite;
           if (file.Open(_T("BankName.dat"),nFlags, &fe))
           {
                CArchive ar(&file, CArchive::store);
                m_map.Serialize(ar);   //序列化存储
           }
       }
}
 
============

CArchive类是使用了缓冲区,即一段内存空间作为临时数据存储地,对CArchive的读写都先依次排列到此缓冲区,当缓冲区满或用户要求时,将此段整理后的数据读写到指定的存储煤质。

一般来说,CArchive封装了对该缓冲区的操作,它的好处是可以少划动硬盘以及提高运行速度。不过对于使用MFC来说,是一个很好的封装。看看其对读写的操作,可见在实际编程上是非常容易出错的。对于这样的类,一定要封装好,作为一个公用函数或公用类调用,否则在实际中像c那样散在代码的各个地方的话,恐怕有时头会大。

有时我想,如果编程在这些地方磨洋工的话,恐怕一个大的工程软件写起来得好长时间。所以说尽量已组件的方式,类的思路来组合前人的算法,技巧也是一种编程的进步。

 

所下列看其对指针的娴熟操作(也是往往出错的啊),

例如双字的插入(写)

CArchive& CArchive::operator<<(DWORD dw)
{
   if (m_lpBufCur + sizeof(DWORD) > m_lpBufMax) //缓冲区空间不够
       Flush();                                  //缓冲区内容提交到实际存储煤质。
   if (!(m_nMode & bNoByteSwap))
     _AfxByteSwap(dw, m_lpBufCur);  //处理字节顺序
   else
     *(DWORD*)m_lpBufCur = dw;      //添入缓冲区
   m_lpBufCur += sizeof(DWORD);     //移动当前指针
   return *this;
}

双字的提取(读)

CArchive& CArchive::operator>>(DWORD& dw)
{
  if (m_lpBufCur + sizeof(DWORD) > m_lpBufMax) //缓冲区要读完了
      FillBuffer(sizeof(DWORD) - (UINT)(m_lpBufMax - m_lpBufCur));  //重新读入内容到缓冲区
   dw = *(DWORD*)m_lpBufCur;  //读取双字
   m_lpBufCur += sizeof(DWORD); //移动当前位置指针
   if (!(m_nMode & bNoByteSwap))
     _AfxByteSwap(dw, (BYTE*)&dw);  //处理字节顺序
   return *this;
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值