目录的打包和解包

由于程序中需要把整个目录打包,所以自己写了打包和解包函数,我对此打包文件的布局设计如下: 

20字节:表明目录结构的起点

 

                                   ……

目录结构起点(前20个字节标明的):

 

文件内容起点:

文件FD结构

文件FD结构

文件内容

 

文件内容

 

目录FD结构

目录FD结构

目录FD结构

                                   ……

20字节:表明目录结构的起点
 
                                   ……
目录结构起点(前20个字节标明的):
 
文件内容起点:
文件FD结构
文件FD结构
文件内容
 
文件内容
 
目录FD结构
目录FD结构
目录FD结构
                                   ……
 上述的FD结构其实就是:
typedef struct stFD
{
 TCHAR szName[MAX_PATH]; // 文件或者目录名
 long nSize;  // 文件内容的大小,以字节表示,如果是目录大小为0
 FILETIME cTime;  // 创建时间
 FILETIME aTime; // 最后访问时间
 FILETIME mTime; // 最后改写时间
 DWORD attribute; // 表明文件的状态
}FD;

打包函数:

void PackDir(LPCTSTR lpszDir, LPCTSTR lpszOutputFile)
{// 给出一个目录,把这个目录打包
 // Param:
 //  lpszDir: 打包目录
 //     lpszOutputFile: 打包后的输出文件名
 
 const int nOffset = 20;
 CFileFind finder;
 CStringList strLst;
 FD fdTmp;
 CFileStatus fileStatus;
 CString strTmp;
 BOOL bWorking;
 CString strDir(_T(""));
 TCHAR *pszFileContent = NULL;
 CFile fileTmp;
 CString strFileDirTmp;
 TCHAR szCnt[nOffset];
 vector<FD> vDirFD;

 if(!finder.FindFile(lpszDir))
 {
  AfxMessageBox("目录不存在");
  return;
 }

 // 创建打包文件
 CFile PackFile;
 if(!PackFile.Open(lpszOutputFile, CFile::modeCreate|CFile::modeReadWrite, NULL))
 {
  AfxMessageBox("创建打包文件出错!");
  return;
 }
 
 // 先把文件开始的nOffset个字节占住,用于表示到目录结构所要偏移的字节数            
 PackFile.SeekToBegin();
 PackFile.Write(szCnt, nOffset); 

 strLst.AddTail(lpszDir);
 
 while(!strLst.IsEmpty())
 {
  strTmp = strLst.GetHead() + _T("//*.*");
  bWorking = finder.FindFile(strTmp);
  if(bWorking)
  {
   while(bWorking)
   {
    bWorking = finder.FindNextFile();
    
    if(finder.IsDots())
     continue;
    
    finder.GetLastAccessTime(&fdTmp.aTime);
    finder.GetCreationTime(&fdTmp.cTime);
    finder.GetLastWriteTime(&fdTmp.mTime);
    
    strFileDirTmp = finder.GetFilePath();
    strFileDirTmp = strFileDirTmp.Right(strFileDirTmp.GetLength() - lstrlen(lpszDir));
    lstrcpy(fdTmp.szName, strFileDirTmp);
    
    fdTmp.nSize = finder.GetLength();
    fdTmp.attribute = GetFileAttributes(finder.GetFilePath());
    
    // 目录
    if(finder.IsDirectory())
    {
     // 保存下来,在后面再写进文件里
     vDirFD.push_back(fdTmp);

     strLst.AddTail(finder.GetFilePath());
     continue;
    }
    
    // 找到文件
    PackFile.SeekToEnd();

    // 将文件结构写进
    PackFile.Write(&fdTmp, sizeof(FD));
    // 将文件内容写进
    pszFileContent = new TCHAR[finder.GetLength()];

    if(!fileTmp.Open(finder.GetFilePath(), CFile::modeRead, NULL))
    {
     CString strErr;
     strErr.Format("写进打包文件时,打开文件%s出错!", finder.GetFilePath());
     AfxMessageBox(strErr);
     return;
    }
    fileTmp.Read(pszFileContent, finder.GetLength());
    PackFile.Write(pszFileContent, finder.GetLength());
    
    delete pszFileContent;
   }
  }
  
  strLst.RemoveHead();
 }
 
 // 在开始的nOffset个字节处写进目录结构偏移量
 DWORD dwCnt = PackFile.SeekToEnd();
 sprintf(szCnt, "%ld", dwCnt);
 PackFile.SeekToBegin();
 PackFile.Write(szCnt, nOffset);

 // 去到最后写进目录结构
 PackFile.SeekToEnd();
 for(int i = 0; i < vDirFD.size(); i++)
 {
  fdTmp = vDirFD[i];
  PackFile.Write(&fdTmp, sizeof(fdTmp));
 }

 PackFile.Close();
}

 

 

 

 

 

解包函数:

void UnPackDir(LPCTSTR lpszInputFile, LPCTSTR lpszDir)
{// 给出一个文件,把这个文件还原为目录
 // Param:
 //  lpszInputFile: 利用PackDir函数打包成的文件
 //  lpszDir: 还原到的目录路径
 
 const int nOffset = 20;
 TCHAR szCnt[nOffset];
 long nOff = 0;
 CString strDir;
 CString strFile;
 FD fdTmp;
 DWORD dwCurPos = 0;
 TCHAR *pszFileContent;

 CFile fileInput;
 if(!fileInput.Open(lpszInputFile, CFile::modeRead, NULL))
 {
  AfxMessageBox("打开输入文件出错!");
  return;
 }

 // 先建立目录结构
 memset(szCnt, 0, nOffset);
 fileInput.Read(szCnt, nOffset);
 nOff = atoi(szCnt);
 // 去到文件目录结构的起点
 fileInput.Seek( nOff, CFile::begin );
 while(!IsFileEnd(fileInput))
 {
  fileInput.Read(&fdTmp, sizeof(FD));
  strDir = lpszDir;
  strDir += fdTmp.szName;

  CreateDirectory(strDir, NULL);
    
  SetFileAttributes(strDir, fdTmp.attribute);
 }

 // 再把文件创建好
 dwCurPos = fileInput.Seek(nOffset, CFile::begin);
 CFile fileTmp;
 while(dwCurPos < nOff)
 {
  fileInput.Read(&fdTmp, sizeof(FD));
  strFile = lpszDir;
  strFile += fdTmp.szName;
  
  if(!fileTmp.Open(strFile, CFile::modeCreate | CFile::modeReadWrite, NULL))
  {
   CString strErr;
   strErr.Format("解包时创建文件%s出错!", strFile);
   AfxMessageBox(strErr);
   return;
  }
  // 把内容复制过去
  pszFileContent = new TCHAR[fdTmp.nSize];
  fileInput.Read(pszFileContent, fdTmp.nSize);
  fileTmp.SeekToBegin();
  fileTmp.Write(pszFileContent, fdTmp.nSize);
  delete pszFileContent;

  // 把文件的属性改变,先关闭再改
  fileTmp.Close();

  CFileStatus rStatus;
  CTime cTime(fdTmp.cTime);
  CTime aTime(fdTmp.aTime);
  CTime mTime(fdTmp.mTime);
  rStatus.m_atime = aTime;
  rStatus.m_ctime = cTime;
  rStatus.m_mtime = mTime;
  rStatus.m_attribute = (BYTE)fdTmp.attribute;
  rStatus.m_size = fdTmp.nSize;
  lstrcpy(rStatus.m_szFullName, strFile);

  CFile::SetStatus(strFile, rStatus);

  dwCurPos = fileInput.GetPosition();  
 }

 fileInput.Close();
}

 


还有一个判断是否到了文件末尾的函数:

BOOL IsFileEnd(CFile &file)
{
 DWORD dwFileLength = file.GetLength();
 DWORD dwFileCurPos = file.GetPosition();
 
 if(dwFileCurPos < dwFileLength)
 {
  return FALSE;
 }
 
 return TRUE;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值