Einzelnen Beitrag anzeigen

Michael II

Registriert seit: 1. Dez 2012
Ort: CH BE Eriswil
760 Beiträge
 
Delphi 11 Alexandria
 
#87

AW: DEC 5.2 String hashen?

  Alt 5. Mai 2017, 11:59
Wenn du den Hash selbst ermitteln musst, dann empfehle ich dir dies Stück für Stück zu tun.

Ich hatte mal Code gepostet, welcher gleich alles las. Das ist natürlich für extrem grosse Files dumm. [Aber für die meisten "normalen Fälle" ausreichend.]


Wenn du über das ganze File hashen willst, dann nimm doch eine vorgefertigte Methode, zum Beispiel

Delphi-Quellcode:
var b : TByte;
    rbs : rawbytestring;

...
...

b := System.hash.THashMD5.GetHashBytesFromFile( );
oder
rbs := System.hash.THashMD5.GetHashStringFromFile( );
Schau dir an, wie GetHashBytesFromFile programmiert ist.

...BytesFromFile liefert dir den 128Bit Hash in 16Bytes, und die ...StringFromFile liefert dir einen hex-String der Länge 32.

[Fritz hat mal eine Version gepostet, welche praktisch 1:1 gleich funktioniert. Die Version Fritz hasht aber bei der letzten Tranche über zu viele Bytes und liefert in fast nur in 1/1MB aller Fälle einen korrekten Wert.]



Wenn du nur über Teile eines Files hashen willst, dann könntest du es wie im Code unten tun (ich habe hier die Bytevariante ausgebaut, die hex Variante kannst du daraus ja leicht gewinnen):



Delphi-Quellcode:
procedure AddHashBytes( var lHasher: THashMD5; const AStream: TStream; von, bis : int64 );
const
   BufferSize = 64*1024;
var
  lStreamBytes: TBytes;
  Lies, SollLesen : int64;
  len : integer;
begin
  if bis >= AStream.size then bis := Astream.size-1;
  if von < 0 then von := 0;
  if bis >= von then
  begin
    setlength(lStreamBytes, BufferSize);
    AStream.Position := von;
    SollLesen := bis-von+1;
    while SollLesen > 0 do
    begin
      if SollLesen >= BufferSize then Lies := BufferSize else Lies := SollLesen;
      len := Astream.ReadData(lStreamBytes, Lies);
      if len = 0 then break;
      dec(SollLesen,len);
      lHasher.Update(lStreamBytes, len);
    end;
  end;
end;



function GetHashFromFile( aFileName : string; vonbis : array of int64 ) : TBytes;
var f : TFileStream;
   LMD5: THashMD5;
   i, len : integer;
   von, bis : int64;

begin
  f := TFileStream.Create( aFileName, fmOpenRead );
 try
  LMD5 := THashMD5.Create;
  LMD5.Reset;
  len := length(vonbis);
  if len < 2 then
  begin
      AddHashBytes( LMD5, f, 0, f.Size-1 );
  end
  else
  begin
      i := 0;
      while len-i >= 2 do
      begin
        von := vonbis[i];
        bis := vonbis[i+1];
        if von < 0 then von := f.Size+von;
        if bis < 0 then bis := f.Size+bis;

        AddHashBytes( LMD5, f, von, bis);
        inc(i,2);
      end;
  end;
  Result := LMD5.HashAsBytes;
 finally
  f.Free;
 end;
end;



Mögliche Aufrufe:
Beispiel 1:
Wenn du von Byte 0 bis 2000 und von Byte 2001 bis ans Ende hashen willst:

GetHashFromFile( filename, [0, 2000, 2001, maxint] );

Damit hashst du ja übers ganze File und erhältst natürlich exakt den gleichen Wert wie via
System.hash.THashMD5.GetHashBytesFromFile( filename );

Beispiel 2:
Wenn du Bytes 192435 - 192450 nicht "mithashen" willst:
GetHashFromFile( filename, [0, 192434, 192451, maxint] );

Beispiel 3:
Negative Werte:
Wenn du die letzten 16 Bytes des Files nicht hashen willst:
GetHashFromFile( filename, [0, -17] );




Ich hoffe, das hilft. Korrekturen bitte direkt an mich - Dankeschön.
Michael Gasser

Geändert von Michael II ( 5. Mai 2017 um 19:55 Uhr)