Respuestas de user532231 y Mike están trabajando en el 99% de los casos, pero hay comprobaciones adicionales que se harán!
Descendientes de TStream pueden ser casi cualquier cosa, por lo no está garantizado que Stream.Read volverá misma cantidad de datos, incluso si las corrientes son de la misma longitud (descendiente corriente también puede descargar los datos, por lo que pueden volver readed = 0 bytes, mientras espera el siguiente fragmento). Las transmisiones también pueden estar en medios totalmente diferentes y el error de lectura de la secuencia puede ocurrir en una sola.
Para obtener un código de funcionamiento del 100%, todas estas comprobaciones deben realizarse. Modifiqué la función de Mike.
Si esta función se utiliza, por ejemplo, para reescribir la secuencia 2 si no es idéntica a la secuencia 1, se deben verificar todos los errores. Cuando el resultado de la función es Verdadero, todo está bien, pero si es Falso, sería muy inteligente verificar si las Corrientes son realmente diferentes o si solo se produjo algún error.
Editado: añadido algunas comprobaciones adicionales, FilesAreIdentical función basada en StreamsAreIdentical y ejemplo de uso.
// Usage example
var lError: Integer;
...
if FilesAreIdentical(lError, 'file1.ext', 'file2.ext')
then Memo1.Lines.Append('Files are identical.')
else case lError of
0: Memo1.Lines.Append('Files are NOT identical!');
1: Memo1.Lines.Append('Files opened, stream read exception raised!');
2: Memo1.Lines.Append('File does not exist!');
3: Memo1.Lines.Append('File open exception raised!');
end; // case
...
// StreamAreIdentical
function StreamsAreIdentical(var aError: Integer;
const aStream1, aStream2: TStream;
const aBlockSize: Integer = 4096): Boolean;
var
lBuffer1: array of byte;
lBuffer2: array of byte;
lBuffer1Readed,
lBuffer2Readed,
lBlockSize: integer;
begin
Result:=False;
aError:=0;
try
if aStream1.Size <> aStream2.Size
then Exit;
aStream1.Position:=0;
aStream2.Position:=0;
if aBlockSize>0
then lBlockSize:=aBlockSize
else lBlockSize:=4096;
SetLength(lBuffer1, lBlockSize);
SetLength(lBuffer2, lBlockSize);
lBuffer1Readed:=1; // just for entering while
while (lBuffer1Readed > 0) and (aStream1.Position < aStream1.Size) do
begin
lBuffer1Readed := aStream1.Read(lBuffer1[0], lBlockSize);
lBuffer2Readed := aStream2.Read(lBuffer2[0], lBlockSize);
if (lBuffer1Readed <> lBuffer2Readed) or ((lBuffer1Readed <> lBlockSize) and (aStream1.Position < aStream1.Size))
then Exit;
if not CompareMem(@lBuffer1[0], @lBuffer2[0], lBuffer1Readed)
then Exit;
end; // while
Result:=True;
except
aError:=1; // stream read exception
end;
end;
// FilesAreIdentical using function StreamsAreIdentical
function FilesAreIdentical(var aError: Integer;
const aFileName1, aFileName2: String;
const aBlockSize: Integer = 4096): Boolean;
var lFileStream1,
lFilestream2: TFileStream;
begin
Result:=False;
try
if not (FileExists(aFileName1) and FileExists(aFileName2))
then begin
aError:=2; // file not found
Exit;
end;
lFileStream1:=nil;
lFileStream2:=nil;
try
lFileStream1:=TfileStream.Create(aFileName1, fmOpenRead or fmShareDenyNone);
lFileStream2:=TFileStream.Create(aFileName2, fmOpenRead or fmShareDenyNone);
result:=StreamsAreIdentical(aError, lFileStream1, lFileStream2, aBlockSize);
finally
if lFileStream2<>nil
then lFileStream2.Free;
if lFileStream1<>nil
then lFileStream1.Free;
end; // finally
except
aError:=3; // file open exception
end; // except
end;
Tal vez sea útil cuando establece ambas posiciones de flujo en 0 antes de comenzar su ciclo. –
O cargue las secuencias enteras en 2 secuencias de memoria y alimente aquellas para compararmem. – Remko
@Uwe Raabe - +1, tienes toda la razón, @Remko - +1, probablemente también estés en lo cierto, espero que CompareMem salga inmediatamente cuando encuentre la diferencia de bytes –