mirror of
https://github.com/doublecmd/doublecmd.git
synced 2026-06-21 09:58:13 +00:00
190 lines
5 KiB
ObjectPascal
190 lines
5 KiB
ObjectPascal
{$mode objfpc}{$H+}
|
|
unit uCompareFiles;
|
|
|
|
interface
|
|
uses
|
|
Classes;
|
|
Type
|
|
TCompareMethod=(cmInternalText, cmInternalBin);
|
|
const
|
|
cColumnSize=10;
|
|
cLineDiverg=50;
|
|
|
|
function CompareFiles(const sLeftFileName, sRightFileName:String; {Var}
|
|
lsLeft, lsRight:TStrings; CompareMethod:TCompareMethod):Integer;
|
|
|
|
implementation
|
|
uses
|
|
SysUtils, uShowMsg, uTextCompare;
|
|
|
|
function ConvertByte(b:Byte):Char;
|
|
begin
|
|
if b in [32..255] then
|
|
Result:=Chr(b)
|
|
else
|
|
Result:='.';
|
|
{ case b of
|
|
0..31: Result:='.';
|
|
32..127: Result:=Chr(b);
|
|
else
|
|
Result:='.';
|
|
end;}
|
|
end;
|
|
|
|
function Byte2Hex(b:Byte):String;
|
|
begin
|
|
Result:=IntToHex(b,2)+' ';
|
|
end;
|
|
|
|
function CompareFilesText(const sLeftFileName, sRightFileName:String; {Var}
|
|
lsLeft, lsRight:TStrings):Integer;
|
|
begin
|
|
lsLeft.LoadFromFile(sLeftFileName);
|
|
lsRight.LoadFromFile(sRightFileName);
|
|
Result:=TextCompare(lsLeft,lsRight);
|
|
end;
|
|
|
|
function CompareFilesBin(const sLeftFileName, sRightFileName:String; {Var}
|
|
lsLeft, lsRight:TStrings):Integer;
|
|
|
|
var
|
|
fLeft, fRight:TFileStream;
|
|
bLeft:Byte;
|
|
bRight:Byte;
|
|
iColumnCount:Integer;
|
|
sLeftLine, sRightLine:String;
|
|
sLeftHexLine, sRightHexLine:String;
|
|
iDif:Integer;
|
|
iLineCount:Integer;
|
|
iDiffed:Integer;
|
|
|
|
procedure ClearLines;
|
|
begin
|
|
sLeftLine:='';
|
|
sRightLine:='';
|
|
sLeftHexLine:='';
|
|
sRightHexLine:='';
|
|
end;
|
|
|
|
Function LineFormat(const sHex, sAscii:String; iLine:Integer):String;
|
|
var
|
|
sDummy:String;
|
|
begin
|
|
sDummy:='';
|
|
if length(sHex)<(cColumnSize*3) then
|
|
sDummy:=StringOfChar('*',cColumnSize*3-length(sHex));
|
|
// Result:=Format('%4d: %s%s %s',[iLine,sHex,sDummy,sAscii]);;
|
|
Result:=Format('%6d: %s%s %s',[iLine,sHex,sDummy,sAscii]);;
|
|
end;
|
|
|
|
begin
|
|
fLeft:=TFileStream.Create(sLeftFileName,fmOpenRead);
|
|
fRight:=TFileStream.Create(sRightFileName,fmOpenRead);
|
|
ClearLines;
|
|
try
|
|
iColumnCount:=0;
|
|
iLineCount:=1;
|
|
iDif:=0; // diferences count
|
|
iDiffed:=0;
|
|
while (fRight.Position<fRight.Size) and (fLeft.Position<fLeft.Size) do
|
|
begin
|
|
fLeft.Read(bLeft,1);
|
|
fRight.Read(bRight,1);
|
|
if bLeft<>bRight then
|
|
begin
|
|
inc(iDif);
|
|
inc(iDiffed);
|
|
end;
|
|
sLeftLine:=sLeftLine+ConvertByte(bLeft);
|
|
sRightLine:=sRightLine+ConvertByte(bRight);
|
|
sRightHexLine:=sRightHexLine+Byte2Hex(bRight);
|
|
sLeftHexLine:=sLeftHexLine+Byte2Hex(bRight);
|
|
inc(iColumnCount);
|
|
if iColumnCount>=cColumnSize then
|
|
begin
|
|
lsLeft.AddObject(LineFormat(sLeftHexLine,sLeftLine, iLineCount), TObject(iDiffed));
|
|
lsRight.AddObject(LineFormat(sRightHexLine,sRightLine, iLineCount),TObject(iDiffed));
|
|
iDiffed:=0;
|
|
ClearLines;
|
|
iColumnCount:=0;
|
|
inc(iLineCount);
|
|
end;
|
|
end;
|
|
// load other data
|
|
if fLeft.Size>fRight.Size then
|
|
begin
|
|
while fLeft.Position<fLeft.Size do
|
|
begin
|
|
fLeft.Read(bLeft,1);
|
|
inc(iDiffed);
|
|
inc(iDif);
|
|
sLeftLine:=sLeftLine+ConvertByte(bLeft);
|
|
sLeftHexLine:=sLeftHexLine+Byte2Hex(bRight);
|
|
inc(iColumnCount);
|
|
if iColumnCount>=cColumnSize then
|
|
begin
|
|
lsLeft.AddObject(LineFormat(sLeftHexLine,sLeftLine, iLineCount),TObject(iDiffed));
|
|
iDiffed:=0;
|
|
sLeftLine:='';
|
|
sLeftHexLine:='';
|
|
iColumnCount:=0;
|
|
inc(iLineCount);
|
|
end;
|
|
end;
|
|
end
|
|
else
|
|
begin
|
|
// load other data
|
|
while fRight.Position<fRight.Size do
|
|
begin
|
|
fRight.Read(bRight,1);
|
|
inc(iDiffed);
|
|
inc(iDif);
|
|
sRightLine:=sRightLine+ConvertByte(bRight);
|
|
sRightHexLine:=sRightHexLine+Byte2Hex(bRight);
|
|
inc(iColumnCount);
|
|
if iColumnCount>=cColumnSize then
|
|
begin
|
|
lsRight.AddObject(LineFormat(sRightHexLine,sRightLine, iLineCount),TObject(iDiffed));
|
|
iDiffed:=0;
|
|
sRightLine:='';
|
|
sRightHexLine:='';
|
|
iColumnCount:=0;
|
|
inc(iLineCount);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
if sRightLine<>'' then
|
|
lsRight.AddObject(LineFormat(sRightHexLine,sRightLine, iLineCount),TObject(iDiffed));
|
|
if sLeftLine<>'' then
|
|
lsLeft.AddObject(LineFormat(sLeftHexLine,sLeftLine, iLineCount),TObject(iDiffed));
|
|
Result:=iDif;
|
|
finally
|
|
FreeAndNil(fLeft);
|
|
FreeAndNil(fRight);
|
|
end;
|
|
end;
|
|
|
|
function CompareFiles(const sLeftFileName, sRightFileName:String; {Var}
|
|
lsLeft, lsRight:TStrings; CompareMethod:TCompareMethod):Integer;
|
|
begin
|
|
assert(lsLeft<>nil,'CompareFiles: lsLeft=nil');
|
|
assert(lsRight<>nil,'CompareFiles: lsRight=nil');
|
|
try
|
|
lsLeft.BeginUpdate;
|
|
lsRight.BeginUpdate;
|
|
|
|
lsLeft.Clear;
|
|
lsRight.Clear;
|
|
case CompareMethod of
|
|
cmInternalText:Result:=CompareFilesText(sLeftFileName,sRightFileName, lsLeft, lsRight);
|
|
cmInternalBin:Result:=CompareFilesBin(sLeftFileName,sRightFileName, lsLeft, lsRight);
|
|
end;
|
|
finally
|
|
lsLeft.EndUpdate;
|
|
lsRight.EndUpdate;
|
|
end;
|
|
end;
|
|
|
|
end.
|