Articles   Members Online:
-Article/Tip Search
-News Group Search over 21 Million news group articles.
-Delphi/Pascal
-CBuilder/C++
-C#Builder/C#
-JBuilder/Java
-Kylix
Member Area
-Home
-Account Center
-Top 10 NEW!!
-Submit Article/Tip
-Forums Upgraded!!
-My Articles
-Edit Information
-Login/Logout
-Become a Member
-Why sign up!
-Newsletter
-Chat Online!
-Indexes NEW!!
Employment
-Build your resume
-Find a job
-Post a job
-Resume Search
Contacts
-Contacts
-Feedbacks
-Link to us
-Privacy/Disclaimer
Embarcadero
Visit Embarcadero
Embarcadero Community
JEDI
Links
How to compare two files and find the differences Turn on/off line numbers in source code. Switch to Orginial background IDE or DSP color Comment or reply to this aritlce/tip for discussion. Bookmark this article to my favorite article(s). Print this article
08-Nov-02
Category
Files Operation
Language
Delphi 3.x
Views
96
User Rating
No Votes
# Votes
0
Replies
0
Publisher:
DSP, Administrator
Reference URL:
DKB
			Author: Tomas Rutkauskas

Does anyone know of sample code that compares two files and indicates if there is a 
difference or not (like FC)? I could use filestreams and compare bit by bit but I'm 
hoping someone has done this in a more optimized fashion.

Answer:

Use CreateFileMapping and compare pointers. Look at my unfinished unit below for an 
example:

1   unit findin;
2   
3   interface
4   
5   uses
6     Windows, SysUtils, findstr;
7   
8   type
9     TFindInFile = class;
10  
11    TFindIn = class
12    protected
13      FFindInFile: TFindInFile;
14      FHandle: THandle;
15      function GetPartNum: Integer; virtual; abstract;
16      function GetPartLen(Index: Integer): Cardinal; virtual; abstract;
17    public
18      constructor Create(FindInFile: TFindInFile; FileName: string); virtual;
19      destructor Destroy; override;
20      function CanUseMem: Boolean; virtual; abstract;
21      function UseMemSize: Cardinal; virtual; abstract;
22      function GetPart(Index: Integer; Len: Cardinal): Pointer; virtual; abstract;
23      property PartNum: Integer read GetPartNum;
24      property PartLen[Index: Integer]: Cardinal read GetPartLen;
25    end;
26  
27    TFindInClass = class of TFindIn;
28  
29    TBMSearchFunc = function(var Buffer; BufLength: Cardinal; var BT: TBMTbl;
30      MatchString: PAnsiChar; var Pos: Cardinal): Boolean;
31  
32    TFindInFile = class
33    protected
34      FFindIn: TFindIn;
35      FFindInClass: TFindInClass;
36      FFindStrParams: PFindStrParams;
37      FMemHandle: THandle;
38      FMem: Pointer;
39      FStrLen: Cardinal;
40      FDriveTp: UINT;
41      FBMSearchFunc: TBMSearchFunc;
42      function GetDriveTp(Root: string): UINT;
43    public
44      constructor Create(FindStrParams: PFindStrParams);
45      destructor Destroy; override;
46      function Find(FileName: string): Cardinal;
47      function SwitchToRoot(Root: string): Boolean; virtual;
48    end;
49  
50    TFindInHDD = class(TFindIn)
51    private
52      FSize: Cardinal;
53    protected
54      FMapPtr: Pointer;
55      function GetPartNum: Integer; override;
56      function GetPartLen(Index: Integer): Cardinal; override;
57    public
58      constructor Create(FindInFile: TFindInFile; FileName: string); override;
59      destructor Destroy; override;
60      function CanUseMem: Boolean; override;
61      function UseMemSize: Cardinal; override;
62      function GetPart(Index: Integer; Len: Cardinal): Pointer; override;
63    end;
64  
65    PIntArr = ^TIntArr;
66    TIntArr = array[0..1] of Cardinal;
67  
68    TFindInRemovable = class(TFindIn)
69    private
70      FSize: Cardinal;
71    protected
72      FPartNum: Integer;
73      function GetPartNum: Integer; override;
74      function GetPartLen(Index: Integer): Cardinal; override;
75    public
76      constructor Create(FindInFile: TFindInFile; FileName: string); override;
77      function CanUseMem: Boolean; override;
78      function UseMemSize: Cardinal; override;
79      function GetPart(Index: Integer; Len: Cardinal): Pointer; override;
80    end;
81  
82  implementation
83  
84  resourcestring
85    SInvalidDrive = 'Invalid drive - "%s".';
86  
87    { TFindIn }
88  
89  constructor TFindIn.Create(FindInFile: TFindInFile; FileName: string);
90  begin
91    inherited Create;
92    FFindInFile := FindInFile;
93    FHandle := CreateFile(PChar(FileName), GENERIC_READ, FILE_SHARE_READ,
94      nil, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, 0);
95    if FHandle = INVALID_HANDLE_VALUE then
96      RaiseLastWin32Error;
97  end;
98  
99  destructor TFindIn.Destroy;
100 begin
101   if FHandle <> 0 then
102     CloseHandle(FHandle);
103   inherited Destroy;
104 end;
105 
106 { TFindInHDD }
107 
108 constructor TFindInHDD.Create(FindInFile: TFindInFile; FileName: string);
109 var
110   hFile: THandle;
111 begin
112   inherited Create(FindInFile, FileName);
113   FSize := GetFileSize(FHandle, nil);
114   hFile := CreateFileMapping(FHandle, nil, PAGE_READONLY, 0, 0, nil);
115   CloseHandle(FHandle);
116   FHandle := hFile;
117   if FHandle <> 0 then
118   begin
119     FMapPtr := MapViewOfFile(FHandle, FILE_MAP_READ, 0, 0, 0);
120     if FMapPtr = nil then
121       RaiseLastWin32Error;
122   end
123   else
124     RaiseLastWin32Error;
125 end;
126 
127 destructor TFindInHDD.Destroy;
128 begin
129   if FMapPtr <> nil then
130     UnmapViewOfFile(FMapPtr);
131   inherited Destroy;
132 end;
133 
134 function TFindInHDD.GetPartNum: Integer;
135 begin
136   Result := 1;
137 end;
138 
139 function TFindInHDD.GetPartLen(Index: Integer): Cardinal;
140 begin
141   Result := FSize;
142 end;
143 
144 function TFindInHDD.GetPart(Index: Integer; Len: Cardinal): Pointer;
145 begin
146   Result := FMapPtr;
147 end;
148 
149 function TFindInHDD.CanUseMem: Boolean;
150 begin
151   Result := False;
152 end;
153 
154 function TFindInHDD.UseMemSize: Cardinal;
155 begin
156   Result := 0;
157 end;
158 
159 { TFindInRemovable }
160 
161 constructor TFindInRemovable.Create(FindInFile: TFindInFile; FileName: string);
162 var
163   S: Cardinal;
164 begin
165   inherited Create(FindInFile, FileName);
166   FSize := GetFileSize(FHandle, nil);
167   if FSize = $FFFFFFFF then
168     RaiseLastWin32Error;
169   S := UseMemSize - Pred(FFindInFile.FStrLen);
170   FPartNum := FSize div S;
171   if FSize mod S <> 0 then
172     Inc(FPartNum);
173 end;
174 
175 function TFindInRemovable.GetPartNum: Integer;
176 begin
177   Result := FPartNum;
178 end;
179 
180 function TFindInRemovable.GetPartLen(Index: Integer): Cardinal;
181 begin
182   Result := UseMemSize;
183   if (Index = Pred(FPartNum)) and (FSize mod (Result - FFindInFile.FStrLen) <> 0) 
184 then
185     Result := FSize - (Result - Pred(FFindInFile.FStrLen)) * Pred(FPartNum);
186 end;
187 
188 function TFindInRemovable.GetPart(Index: Integer; Len: Cardinal): Pointer;
189 var
190   Dist: ULONG;
191   Reading: DWORD;
192 begin
193   Result := FFindInFile.FMem;
194   Dist := Index * (UseMemSize - Pred(FFindInFile.FStrLen));
195   SetFilePointer(FHandle, Dist, nil, FILE_BEGIN);
196   if not ReadFile(FHandle, Result^, Len, Reading, nil) then
197     RaiseLastWin32Error;
198 end;
199 
200 function TFindInRemovable.CanUseMem: Boolean;
201 begin
202   Result := True;
203 end;
204 
205 function TFindInRemovable.UseMemSize: Cardinal;
206 begin
207   Result := 8; {512 * 1024;}
208 end;
209 
210 { TFindInFile }
211 
212 function Max(V1, V2: Integer): Integer; assembler; register;
213 asm
214   CMP  EAX,EDX
215   JG   @@1
216   MOV  EAX,EDX
217 @@1:
218 end;
219 
220 constructor TFindInFile.Create(FindStrParams: PFindStrParams);
221 var
222   I: Integer;
223 begin
224   inherited Create;
225   FDriveTp := $FFFFFFFF;
226   FFindStrParams := FindStrParams;
227   if FFindStrParams^.CaseSensitive then
228     FBMSearchFunc := BMSearch
229   else
230     FBMSearchFunc := BMSearchUC;
231   FStrLen := 0;
232   for I := 0 to Pred(FFindStrParams^.Substr.Count) do
233     FStrLen := Max(FStrLen, length(FFindStrParams^.Substr[I]));
234 end;
235 
236 destructor TFindInFile.Destroy;
237 begin
238   if FMemHandle <> 0 then
239   begin
240     GlobalUnlock(FMemHandle);
241     GlobalFree(FMemHandle);
242   end;
243   inherited Destroy;
244 end;
245 
246 function TFindInFile.GetDriveTp(Root: string): UINT;
247 begin
248   Result := GetDriveType(PChar(ExtractFileDrive(Root) + '\'));
249 end;
250 
251 function TFindInFile.Find(FileName: string): Cardinal;
252 var
253   I, J, K: Integer;
254   L: Cardinal;
255   P: Pointer;
256   PI: PFindStrInfo;
257   BMSFunc: TBMSFunc;
258 begin
259   Result := NotFound;
260   FFindIn := FFindInClass.Create(Self, FileName);
261   try
262     if FFindIn.CanUseMem and (FMem = nil) then
263     begin
264       FMemHandle := GlobalAlloc(GMEM_MOVEABLE, FFindIn.UseMemSize);
265       if FMemHandle = 0 then
266         RaiseLastWin32Error;
267       FMem := GlobalLock(FMemHandle);
268     end;
269     for I := 0 to Pred(FFindIn.PartNum) do
270       for J := 0 to Pred(FFindStrParams^.Substr.Count) do
271       begin
272         L := FFindIn.PartLen[I];
273         P := FFindIn.GetPart(I, L);
274         Result := FindString(P^, L, J, FFindStrParams);
275         PI := PFindStrInfo(FFindStrParams.Substr.Objects[J]);
276         if FBMSearchFunc(P^, L, PI^.BMTbl, PI^.FindS, Result) then
277         begin
278           if I > 0 then
279             for K := 1 to I - 1 do
280               Inc(Result, FFindIn.PartLen[K]);
281           Exit;
282         end;
283       end;
284   finally
285     FFindIn.Free;
286   end;
287 end;
288 
289 function TFindInFile.SwitchToRoot(Root: string): Boolean;
290 var
291   Tp: UINT;
292 begin
293   Tp := GetDriveTp(Root);
294   if Tp <> FDriveTp then
295     case Tp of
296       0, 1: Exception.CreateFmt(SInvalidDrive, [Root]);
297       DRIVE_FIXED: FFindInClass := TFindInHDD;
298     else
299       {DRIVE_REMOVABLE:
300        DRIVE_REMOTE:
301        DRIVE_CDROM:
302        DRIVE_RAMDISK:}
303       FFindInClass := TFindInRemovable;
304     end;
305 end;
306 
307 end.


			
Vote: How useful do you find this Article/Tip?
Bad Excellent
1 2 3 4 5 6 7 8 9 10

 

Advertisement
Share this page
Advertisement
Download from Google

Copyright © Mendozi Enterprises LLC