Description: Originally, I wanted to find a program to synchronize the data folder on my PC and notebook. Of course, the boss should be BEYOND COMPARE in this application, but unfortunately downloaded one, discovery and registration, even the trial is not allowed, so I took a three hours to write one, provide it, if you have a good suggestion, tell me; if you are writing this procedure, you can refer to :), there is what I originally intended to imitate Beyond Compare Make a packaged clistctrl extension class, and later found that I have to do UI and I have to do it. I have to take a lot of effort, so I will be lazy. If the brother is willing to achieve, I can directly implement it on my basics. It's okay. In addition, just finished the Martin Fowler's
2. Configuration of folder Tree: For ease of comparison, I don't use ID Array format definition trees, and the use of the chain list is to be able to compare recursive comparisons in comparison. The specific method is to recutably the same layer of the same level of the tree. Calling method: Simple code as follows: cfldcmptree tree; tree.parsefolder (szleftpath, szrightpath); file: fldpstruct.hfldcmpstruct.cpp Usage: This, don't have to say it, huh, huh, join your own project.
Header //// File: Fldcmpstruct.h // Written By Alva Chien, 2003.3.24 / / ============================= =================================================== // NOTE: // TO avoid hard code mission, I have change some classes members into // public property, so, you need fix this (ah, a hard work) before you put // this file into a security using.//#ifndef _H_FLDCMP_STRUCT_ # define _H_FLDCMP_STRUCT_ // User bitset to compare file # include
GetFileSize (HFILE, NULL); if (dwsize == invalid_file_size) dwsize = 0; CloseHandle (HFILE); #ELSE IFSTREAM IN (LPSZFILE); Assert (in! = Null); in.seekg (0, iOS :: End); streampos pos = in.tellg (); return (dword) POS; #ENDIF / / _NOT_USE_STL} #ENDIF / / / _NOUSE_AUSE_ALLIB _ / / // Declarations // Folder Compare FunctionTyPedef Int (* Pfnfcmpfunc) (LPARAM, LPARAM , LPARAM); class CFldCmpFileNode; class CFldCmpNode; typedef CFldCmpFileNode * CFldCmpFileNodePtr; typedef CFldCmpNode * CFldCmpNodePtr; typedef CTypedPtrArray
======================================================== cfldcmpfilenode const CFldCmpFileNode & fn); CFldCmpFileNode & operator = (const CFldCmpFileNode & fn); // Operationpublic: // Clean data void cleanData (); // Get family nodes UINT GetFamilyNodeNumber () const; // Memberspublic: // File item CString m_strName; BOOL m_bFolder; COleDateTime m_dtModified; DWORD m_dwSize; // Used to build the tree CFldCmpFileNode * m_pFather; CFldCmpFileNodePtrArray m_arChildPtrs; UINT m_nLevel; // No used DWORD m_dwData;}; //// class CFldCmpFileTreeclass CFldCmpFileTree {// Constructorpublic: CFldCmpFileTree (); virtual ~ CFldCmpFileTree (); // Opertionpublic: // Parse folder BOOL ParseFolder (LPCTSTR lpszPath, CFldCmpFileNodePtr pFa = NULL, UINT nLevel = 0); // Clean data void cleanData (); // Get node number UINT GetNodeNumber () const ; // Get Root Array Const Cfldcmpfilenode () const {return m_arrootptrs;} #ifdef _debug // Display Tree Info Void Display DebugInfo (CFldCmpFileNodePtr pFather = NULL); # endif // _DEBUG // Membersprotected: // Root item array CFldCmpFileNodePtrArray m_arRootPtrs;}; //// class CFldCmpNodeclass CFldCmpNode {// Constructorpublic: CFldCmpNode (); virtual ~ CFldCmpNode (); CFldCmpNode (const cfldcmpnode & cn); cfldcmpnode & operator = (const cfldcmpnode & cn); // Operationpublic: // clean data void cleandata (); // get family nodes uint getFamilyNodenumber () const;
// Compare two node, used for sort int Compare (const CFldCmpNode & nc) const; // Memberspublic: FldCmpType m_type; // Type CString m_strName; // Name COleDateTime m_dtLeft; // Left last modified time COleDateTime m_dtRight; // Right last modified time DWORD m_dwLeftSize; // Left file size DWORD m_dwRightSize; // Right file size BOOL m_bFolder; // Folder or not // Used to build the tree CFldCmpNodePtr m_pFather; // Pointer of father node CFldCmpNodePtrArray m_arChildPtrs; // Children node pointer array UINT m_nLevel; // Level, from the root // No used DWORD m_dwData;}; //// class CFldCmpTreeclass CFldCmpTree {// Constrcutionpublic: CFldCmpTree (); virtual ~ CFldCmpTree (); // Interfacepublic: // Clean data void cleanData (); # ifdef _DEBUG // Display tree info void DisplayDebugInfo (CFldCmpNodePtr pFather = NULL); # endif // _DEBUG // Get node number UINT GetNodeNumber () const; // Combine file tree BOOL ParseFolder (LPCTSTR lpszLeft, LPCTSTR LPSZRI ght); // Get root array const CFldCmpNodePtrArray & GetRootArray () const {return m_arRootPtrs;} // Sort void Sort (); // Compare function void SetCustomSortFunc (PFNFCCMPFUNC); // Get node full path CString GetNodeFullPath (const CFldCmpNodePtr pNode, BOOL bLeft = TRUE) const; // Operationsprotected: // Combine file tree BOOL CombineFileTrees (const CFldCmpFileTree & treeLeft, const CFldCmpFileTree & treeRight); // Copy left file tree BOOL CopyLeftFileTree (const CFldCmpFileNodePtrArray & arNodePtrs, CFldCmpNodePtr pFather = NULL); // Combine Right File Tree Bool Combinerighttree (Const CfldcmpfilenodeptraftTRAY & ArfilenodePTRS, Cfldcmpnodeptr Pfather =
NULL); // Sort function void SortArray (CFldCmpNodePtrArray & arArray); // Membersprotected: // Root item array CFldCmpNodePtrArray m_arRootPtrs; // File's compare function PFNFCCMPFUNC m_pFnFileCmp; // Left path CString m_strLeftPath; // Right path CString m_strRightPath;}; #ENDIF / / _H_FLDCMP_STRUCT_
Implement the top half of the file: //// File: fldcmpstruct.cpp // Written by Alva Chien, 2004.3.24 // # include "stdafx.h" #include "fdcmpstruct.h" //// default file compare function / / Support a default compare functionint FCS_DefaultFileCmp (LPARAM lpNode, LPARAM lpszLeftFile, LPARAM lpszRightFile) {ASSERT ((lpNode = NULL) && (lpszLeftFile = NULL) && (lpszRightFile = NULL)!!!); if ((lpNode == NULL) || (lpszLeftFile == NULL) || (lpszRightFile == NULL)) return FALSE; CFldCmpNodePtr pNode = (CFldCmpNodePtr) lpNode;? if (pNode-> m_bFolder) // Folder return 0; DWORD dwSizeLeft = pNode-> m_dwLeftSize, dwSizeRight = pNode-> m_dwRightSize; int nRst = 0; BOOL bContinue = FALSE;! if (dwSizeLeft == dwSizeRight) {#if defined (_NOT_USE_STL) // Read the file content ifstream inLeft ((LPCTSTR) lpszLeftFile); ifstream inRight ( (LPCTSTSTSTSTSTSTSTSTFILE); Assert! = Null) && (INRIGHT! = NULL)); strstream strright, strright; strright << inleft.rdbuf (); strright << INRIGHT.RDBUF (); inleft.close ); INRIG Ht.close (); // in 32 bits computers, sizeof (byte) == 8, so 256 * 8 => 2048 char * PLEFT = strright.str (); char * pRight = strright.str (); int NTIME = DWSIZELEFT / 256; IF (DWSIZELEFT% 256) NTIME = 1; // Hard Work Again, 55555555 .... for (INT i = 0; I
BSLEFT & = BSRight; IF (ncount! = bsleft ()) {// not Same! Out! bcontinue = true; break;}} else {bitset <2048> BSLEFT (PLEFT I * 2048); bitset <2048 > BSRIGHT (PRIGHT I * 2048); int ncount = bsleft.count (); bsleft & = bsright; if (ncount! = Bsleft.count ()) {// NOT SAME! OUT! BCONTINUE = True; Break;} }} Delete strright.str (); delete strright.str (); # else lpbyte pleft = new byte [dwsizeleft]; lpbyte pryt = new byte [dwsizeleft]; assert (Pleft! = Null) && (PLEFT! = Null) && (PRIGHT! = Null )); CFile fileLeft, fileRight; if (fileLeft.Open ((LPCTSTR) lpszLeftFile, CFile :: modeRead)) {fileLeft.ReadHuge (pLeft, dwSizeLeft); fileLeft.Close ();} if (fileRight.Open ((LPCTSTR LpszrightFile, cfile :: modeRead) {Fileright.Readhuge (PRIGHT, DWSIZELEFT); Fileright.close ();} if (cstract) == 0) bcontinue = false; delete [ ] PLE ft; pleft = null; delete [] PRIGHT; PRight = null; #ENDIF / /! _NOT_USE_STL if (! bcontinue) return 0;} // no same, compare it by the time if (pnode-> m_dtleft> pnode-> m_dtRight) nRst = 1; else if (pNode-> m_dtLeft
// Used for arrange m_dwData = 0;} // DecomstructorCFldCmpFileNode :: ~ CFldCmpFileNode () {CleanData ();} // Copy constructorCFldCmpFileNode :: CFldCmpFileNode (const CFldCmpFileNode & fn) {* this = fn;} // Override operator = CFldCmpFileNode & CFldCmpFileNode :: operator = (const CFldCmpFileNode & fn) {if (this = & fn!) {m_strName = fn.m_strName; m_bFolder = fn.m_bFolder; m_dtModified = fn.m_dtModified; m_dwSize = fn.m_dwSize; // Used to build the tree m_pFather = fn.m_pFather; m_arChildPtrs.RemoveAll (); m_arChildPtrs.Copy (fn.m_arChildPtrs); m_nLevel = fn.m_nLevel; // Used for arrange m_dwData = fn.m_dwData;} return * this;} // Clean datavoid CFldCmpFileNode: : Cleandata () {for (int i = 0; i
GetFamilyNodeNumber (); return nCount;} // Parse folderBOOL CFldCmpFileTree :: ParseFolder (LPCTSTR lpszPath, CFldCmpFileNodePtr pFa, UINT nLevel) {ASSERT (lpszPath = NULL!); If (lpszPath == NULL) return FALSE; CString str = lpszPath; IF (str.Isempty ()) Return False; str.trimright (); str.trimright (_t ('//')); str = _t ("//*.*"); // Start Working for Files CFileFind finder; BOOL bWorking = finder.FindFile (str); while (bWorking) {bWorking = finder.FindNextFile (); if (finder.IsDots ()) continue; WIN32_FILE_ATTRIBUTE_DATA fad; CFldCmpFileNodePtr pNode = new CFldCmpFileNode; ASSERT (pNode =! NULL); if (pnode == null) Return false; pnode-> m_strname = finder.getFileName (); pnode-> m_nlevel = NLVEL; pnode-> m_pfather = pfa; if (Finder.Indirectory ()) {PNODE-> M_bfolder = true; // add it t ARRAY IF (PFA == Null) m_arrootptrs.add (pnode); Else Pfa-> m_archildPTRS.Add (PNode); // Recursiving ... if return FALSE (ParseFolder (finder.GetFilePath (), pNode, nLevel 1)!);} Else {pNode-> m_bFolder = FALSE; if (GetFileAttributesEx (finder.GetFilePath (), GetFileExInfoStandard, & fad)! = FALSE) {pNode-> m_dtModified = (COleDateTime) fad.ftLastWriteTime; #ifdef _NOUSE_ACLIB_ pNode-> m_dwSize = FCS_GetFileSize (finder.GetFilePath ()); # else pNode-> m_dwSize = ACC_GetFileSize (finder.GetFilePath ()); # ENDIF / / _NOUSE_ACLIB_} // Add IT IF (PFA ==
NULL) m_arrootptrs.add (pnode); Else Pfa-> m_archildptrs.add (pnode);}} Return True;} // clean datavoid cfldcmpfiletree :: cleandata () {for (int i = 0; i
Implementation files intermediate portion //// class CFldCmpNode // ConstructorCFldCmpNode :: CFldCmpNode () {m_type = FCT_MATCH; // Type m_strName = _T ( ""); // Name m_dtLeft = COleDateTime :: GetCurrentTime (); // Left last modified time m_dtRight = COleDateTime :: GetCurrentTime (); // Right last modified time m_dwLeftSize = 0; // Left file size m_dwRightSize = 0; // Right file size m_bFolder = FALSE; // Folder or not // Used to build the Tree m_pfather = null; // Pointer of Father node m_archildptrs.setsize (0); // children node pointer array m_nlevel = (uint) -1; // Level, from the root // used data m_dwdata = 0;} cfldcmpnode: : ~ CFldCmpNode () {cleanData ();} CFldCmpNode :: CFldCmpNode (const CFldCmpNode & cn) {* this = cn;} CFldCmpNode & CFldCmpNode :: operator = (const CFldCmpNode & cn) {if (! this = & cn) {m_type = cn. m_type; // type m_strname = cn.m_strname; // name m_dtleft = cn.m_dtleft; // Left last modified time m_dtright = cn.m_dtright; // Right Last Modified Time M_DWLEF tSize = cn.m_dwLeftSize; // Left file size m_dwRightSize = cn.m_dwRightSize; // Right file size m_bFolder = cn.m_bFolder; // Folder or not // Used to build the tree m_pFather = cn.m_pFather; // Pointer of father node m_arChildPtrs.RemoveAll (); m_arChildPtrs.Copy (cn.m_arChildPtrs); m_nLevel = cn.m_nLevel; // Level, from the root // Used for arrange m_dwData = cn.m_dwData;} return * this;} // Clean Datavoid cfldcmpnode :: cleandata () {for (int i = 0; i pNode-> CleanData (); # ifdef _NOUSE_ACLIB_ FCS_SAFEDEL (pNode); # else ACC_SAFEDEL (pNode); # endif // _NOUSE_ACLIB_} m_arChildPtrs.RemoveAll ();} // Get family nodesUINT CFldCmpNode :: GetFamilyNodeNumber () const {UINT nCount = 0; for (int i = 0; i m_pfather == null)? _T ("none): pfather-> m_pfather-> m_strname, pfather-> m_dwleftsize, pfather-> m_dwrightsize, pfather-> m_archildptrs.getsize ());} for (int i = 0; i // Combine the right treeBOOL CFldCmpTree :: CombineRightTree (const CFldCmpFileNodePtrArray & arFileNodePtrs, CFldCmpNodePtr pFather) {CFldCmpNodePtrArray & arNodes = (pFather == NULL) m_arRootPtrs:? PFather-> m_arChildPtrs; BOOL bExist = FALSE; int i = 0; int nArSize = arNodes .GetSize (); for (; i m_bFolder = pFileNode-> m_bFolder; pNode-> m_pFather = pFather; arNodes.Add (pNode);} // The children pointers CombineRightTree (pFileNode-> m_arChildPtrs, pNode);} return TRUE;} // Combine the file treeBOOL CFldCmpTree: : CombineFileTrees (const CFldCmpFileTree & treeLeft, const CFldCmpFileTree & treeRight) {cleanData (); // First: Copy the left CopyLeftFileTree (treeLeft.GetRootArray ()); // Trace info TRACE0 ( "/ nAfter copy left file tree ... == =========================================== / n "); Trace (" / TTotal Number IS% D ... ======================= / n / n ", getnodenumber ()); DisplayDebugInfo (); trace0 (" / n "); // second: Combine The right Tree Combinerighttree ()); // trace info trace0 ("/ NAFTER Combine right file tree ... ====================== ============= / n "); Trace (" / Ttotal Number IS% D ... ==================== == / N / N ", getnodenumber ()); DisplayDebuginfo (); trace0 (" / n "); return true;} / sort the arrayvoid cfldcmptree :: SortArray (Cfldcmpnodeptra Rray & Ararray) {Int nsize = Ararray.getsize (); INT i = 0; // sort it for (; i