Frage

ich brauche, wenn zwei miteinander vergleichen TStream Nachkomme haben den gleichen Inhalt . Das einzige interessantes Ergebnis ist für mich die boolean Ja / Nein.

Ich bin, um Code geht eine einfache Schleife Überprüfung Byte für Byte den Inhalt des Streams.

Aber ich bin neugierig wissen, ob es eine bereits vorhandene Funktion ist. Ich habe nicht gefunden jede innerhalb DelphiXE oder JCL / JVCL Libs.

Natürlich haben die beiden Ströme die gleiche Größe!

War es hilfreich?

Lösung

Genau, wie Nickolay O. sagte Sie Ihren Strom in Blöcke lesen und CompareMem verwenden. Hier ist ein Beispiel (einschließlich Größe Test) ...

function IsIdenticalStreams(Source, Destination: TStream): boolean;
const Block_Size = 4096;

var Buffer_1: array[0..Block_Size-1] of byte;
    Buffer_2: array[0..Block_Size-1] of byte;
    Buffer_Length: integer;

begin
  Result := False;

  if Source.Size <> Destination.Size then
    Exit;

  while Source.Position < Source.Size do
    begin
      Buffer_Length := Source.Read(Buffer_1, Block_Size);
      Destination.Read(Buffer_2, Block_Size);

      if not CompareMem(@Buffer_1, @Buffer_2, Buffer_Length) then
        Exit;
    end;

  Result := True;
end;

Andere Tipps

Die IsIdenticalStreams Funktion von daemon_x geschrieben ist ausgezeichnet - aber muss man Anpassung richtig an die Arbeit. (Uwe Raabe fing das Problem bereits.) Es ist wichtig, dass Sie die Stream-Positionen zurückgesetzt, bevor die Schleife Anfahr - oder dieses Verfahren wird wahrscheinlich eine falsche TRUE zurück, wenn die beiden Ströme bereits außerhalb dieser Funktion abgerufen wurden.

Dies ist die letzte Lösung, die jedes Mal funktioniert. Ich umbenannt nur die Funktion meiner Namenskonventionen zu entsprechen. Danke daemon_x für die elegante Lösung.

function StreamsAreIdentical(Stream1, Stream2: TStream): boolean;
const
  Block_Size = 4096;

var
  Buffer_1: array[0..Block_Size-1] of byte;
  Buffer_2: array[0..Block_Size-1] of byte;
  Buffer_Length: integer;

begin

  Result := False;

  if Stream1.Size <> Stream2.Size then exit;

  // These two added lines are critical for proper operation 
  Stream1.Position := 0;
  Stream2.Position := 0;

  while Stream1.Position < Stream1.Size do
  begin

    Buffer_Length := Stream1.Read(Buffer_1, Block_Size);
    Stream2.Read(Buffer_2, Block_Size);
    if not CompareMem(@Buffer_1, @Buffer_2, Buffer_Length) then exit;

  end;

  Result := True;

end;

Es gibt keine integrierte Funktion. Nur eine Sache, die ich empfehlen kann -. Las nicht Byte-zu-Byte, sondern Blöcke von 16-64kbytes verwenden, die viel schneller wäre

Antworten von user532231 und Mike sind in 99% der Fälle zu arbeiten, aber es gibt zusätzliche Kontrollen vorgenommen werden

Nachkommen von TStream kann fast alles sein, so ist es nicht garantiert, dass Stream.Read gleiche Datenmenge zurück , auch wenn Ströme sind von gleicher Länge (Strom Nachkomme auch Daten herunterladen können, so kann return readed = 0 Byte, während für die nächste Brocken wartet). Streams können auch auf sein completelly verschiedenen Medien und Stream-Lesefehler auftreten, auf konnte nur eine.

Für 100% Arbeits Code alle sollten diese Kontrollen durchgeführt werden. Ich veränderte die Funktion von Mike.

Wenn diese Funktion zum Beispiel verwendet wird Strom neu zu schreiben 2, wenn nicht identisch mit Stream1 sollte alle Fehler überprüft werden. Wenn die Funktion Ergebnis Wahr ist, Everthing ist in Ordnung, aber wenn es falsch ist, wäre es sehr klug sein, zu überprüfen, ob Streams tatsächlich unterschiedlich sind oder nur einige Fehler ist aufgetreten.

Edited:. hinzugefügt einige zusätzliche Kontrollen, FilesAreIdentical Funktion basierend auf StreamsAreIdentical und Verwendungsbeispiel

// 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;
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top