在两个目录中寻找差异文件

 开发环境
VS2005 SP1,BOOST 1.36, STL, MarkUp


Snap.h

#pragma once

 

class CSnap

{

public:

CSnap(void);

 

~CSnap(void);

 

// 制作快照,并保存为 xml 文件

void SaveSnap( const char* szFileName );

 

private:

char* m_pszCurDir; //当前路径

};



Snap.cpp

#include <iostream>

#include <Windows.h>

#include <string>

#include <boost/lexical_cast.hpp>

#include <boost/algorithm/string.hpp>

#include <boost/crc.hpp>

#include <boost/filesystem/path.hpp>

#include <boost/filesystem/operations.hpp>

#include <boost/filesystem.hpp>

 

#include "Snap.h"

#include "Markup.h"

 

using namespace std;

using namespace boost;

namespace fs = boost::filesystem;

 

const char* g_FolderName = "Update//";

 

CSnap::CSnap(void)

{

//默认路径是程序 .exe 所在的路径

m_pszCurDir = new char[ MAX_PATH ];

::GetCurrentDirectory( MAX_PATH, m_pszCurDir );

int nLen = strlen( m_pszCurDir );

m_pszCurDir[ nLen ] = '//';

m_pszCurDir[ nLen + 1 ] = '/0';

}

 

CSnap::~CSnap(void)

{

delete [] m_pszCurDir;

}

 

 

 

 

// 制作快照,并保存为 xml 文件

void CSnap::SaveSnap(  const char* szFileName )

{

char szPath[ MAX_PATH ];

::GetModuleFileName( NULL, szPath, MAX_PATH );

 

std::string strFullSnapPath = std::string( m_pszCurDir ) + szFileName;

 

CMarkup xml;

xml.AddElem( "ourgame" );

xml.IntoElem();

 

std::string strNodeName = "file";

int nIndex = 1;

 

std::string strSnapPath = std::string( m_pszCurDir ) + std::string( g_FolderName );

 

fs::path fsPath( strSnapPath ,fs::native );

 

if ( !fs::exists( fsPath ) )

{

return;

}

 

fs::recursive_directory_iterator beg_iter(fsPath);

fs::recursive_directory_iterator end_iter;

for (; beg_iter != end_iter; ++beg_iter)

{

if (fs::is_directory(*beg_iter))

{

continue;

}

else

{           

uintmax_t filesize = fs::file_size(*beg_iter);               

 

std::string strFullPathFile = beg_iter->path().file_string();

//std::cout << strFullPathFile << endl;

 

// .exe 对自己和 快照文件 不做快照

//if ( ( strFullPathFile == szPath ) || ( strFullPathFile == strFullSnapPath ) )

//{

// //std::cout << strFullPathFile << endl;

// continue;

//}

 

char* pszBuf = new char[ filesize ];

memset(pszBuf, 0, filesize);

std::locale prev_loc = std::locale::global( std::locale("chs") ); // 没有这一句的话,文件打开失败

ifstream file;           

file.open( strFullPathFile.c_str(),ios_base::in | ios_base::binary );  

if(file.is_open())

{                   

file.read(pszBuf,filesize);

file.close();

boost::crc_32_type ResultCrc32;

//计算文件的CRC值

ResultCrc32.process_block( pszBuf, pszBuf + filesize*sizeof(char) );

unsigned int nCrc32 = ResultCrc32.checksum();

 

std::locale::global( prev_loc ); // 没有这一句的话,文件中的中文无法输出,且wcout输出中文也失败

//cout << strFullPathFile << endl;

file.close(); 

 

std::string strCurrentNodeName = strNodeName + boost::lexical_cast< std::string >( nIndex++ );

std::string strFile = boost::replace_first_copy( strFullPathFile, m_pszCurDir, "" );

 

//std::cout << strFullPathFile << std::endl;

//std::cout << m_pszCurDir << std::endl;

//std::cout << strFile << std::endl;

 

xml.AddElem( strCurrentNodeName );

xml.IntoElem();

xml.AddElem( "name", strFile );

xml.AddElem( "checkcode", boost::lexical_cast< std::string >( nCrc32 )  );

xml.OutOfElem();

}

else

{

file.close();      

}

 

delete [] pszBuf;

}

}

xml.Save( szFileName );

}

 


测试程序

#include <iostream>

#include "Snap.h"

 

//#include <Windows.h>

using namespace std;


void main(void)
{   
     CSnap snap;

     snap.SaveSnap( "1.xml" );

 


    std::system("pause");
    return;
}

 


将上面的代码编译成 exe,然后在 exe 的目录,新建一个 "Update" 文件夹,并在其中拷贝若干文件,然后运行 exe 程序,会生成一个 "1.xml" 的文件;里面使用 XML 格式记录了 Update 文件夹下面所有的文件信息(文件名,CRC32码)

 

 

假如现在有2个 XML 文件,里面分别记录了服务端上 Update 文件夹 和 客户端 Update 文件夹下面的文件信息,现在要对比出差异文件,可以使用下面的函数

 

 

//快速检查某个文件或者目录是否存在

BOOL FileExists(LPCTSTR lpszFileName, BOOL bIsDirCheck)

{

//试图取得文件属性

DWORD dwAttributes = GetFileAttributes(lpszFileName);

if(dwAttributes == 0xFFFFFFFF)

return FALSE;

if((dwAttributes & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY)

{

if(bIsDirCheck)

return TRUE;

else

return FALSE;

}

else

{

if(!bIsDirCheck)

return TRUE;

else

return FALSE;

}    

 

bool GetSnapInfo( const char* szSnap, std::map< std::string, std::string >& mapFileName_CheckCode )

{

if ( NULL == szSnap )

{

return false;

}

 

if ( FALSE == FileExists( szSnap, FALSE ) )

{

return false;

}

 

mapFileName_CheckCode.clear();

 

CMarkup xml;

xml.Load( szSnap );

std::string strNodeName = "file";

int nIndex = 1;

xml.IntoElem();

std::string strCurrentNodeName = strNodeName + boost::lexical_cast< std::string >( nIndex++ );

 

while ( xml.FindChildElem( strCurrentNodeName ) )

{

xml.IntoElem();

xml.FindChildElem( "name" );

std::string strFileName = xml.GetChildData();

//cout << strFileName << endl;

xml.FindChildElem( "checkcode" );

std::string strCheckCode = xml.GetChildData();

//cout << strCheckCode << endl;

mapFileName_CheckCode[ strFileName ] = strCheckCode;

xml.OutOfElem();

strCurrentNodeName = strNodeName + boost::lexical_cast< std::string >( nIndex++ );

}

 

return true;

}

 

// szSrvSnap 和 szSnap2 表示两个快照文件的全路径

// vecSnap 存放差异文件信息

void GetDiffFile( const char* szSrvSnap, const char* szCliSnap, std::vector< std::string >& vecSnap )

{

if ( ( NULL == szSrvSnap ) || ( NULL == szCliSnap ) )

{

return;

}

 

if ( ( FALSE == FileExists( szSrvSnap, FALSE ) ) || ( FALSE == FileExists( szCliSnap, FALSE ) ) )

{

return;

}

 

std::map< std::string, std::string > mapSrvFileName_CheckCode;

std::map< std::string, std::string > mapCliFileName_CheckCode;

GetSnapInfo( szSrvSnap, mapSrvFileName_CheckCode );

GetSnapInfo( szCliSnap, mapCliFileName_CheckCode );

 

//cout << mapSrvFileName_CheckCode.size() << endl;

//cout << mapCliFileName_CheckCode.size() << endl;

 

vecSnap.clear();

std::map< std::string, std::string >::iterator iterSrv = mapSrvFileName_CheckCode.begin();

for ( ; iterSrv!=mapSrvFileName_CheckCode.end(); ++iterSrv )

{

std::map< std::string, std::string >::iterator iterCli = mapCliFileName_CheckCode.find( iterSrv->first );

//找到了

if ( iterCli != mapCliFileName_CheckCode.end() )

{

//对比 CRC32 码

if ( iterSrv->second != iterCli->second )

{

vecSnap.push_back( iterSrv->first );

}

}

//没找到

else

{

vecSnap.push_back( iterSrv->first );

}

}

}


鄙人较懒,没有考虑太多,上面的代码实现了基本的快照对比功能;关于程序性能和功能,没有考虑,路过的朋友如果有更好的方法,麻烦贴上来给我学习用;祝大家身体健康

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值