12. juni 2002 - 14:12Der er
39 kommentarer og 1 løsning
Sammenligne filer
Hejsa
Jeg søger en stump kode, der er i stand til at sammenligne alle slags filer, både binære og textfiler. Og fortælle mig, om de er forskellige. Jeg behøver ingen information om hvor i filerne der er forskelle, bare en boolean eller noget i den retning. Er der en af jer der har en stump kode liggende?
jeg har en enkelt gang postet den før på eksperten . Der var det også kommentarer med :
Function GetCheckSum (const FileName : TFileName) : Integer; var F : File of Integer; Fsize : Integer; Buffer : Array [0..500] of Integer; begin FileMode := 0; AssignFile ( F , FileName); Reset ( F ); Seek ( F , FileSize ( F ) div 2); Fsize := FileSize( F )-1-FilePos( F ); if Fsize > 500 then Fsize := 500; BlockRead ( F, Buffer, Fsize); CloseFile ( F ); asm xor eax, eax //NULSTILL eax det skal bruges til at tælle sammen i xor ecx, ecx //NULSTILL ecx det skal bruges til at holde vores tælle variabel lea edx , Buffer //Put adressen på Buffer over i edx registeret. @again: //En label vi kan hoppe til PRÆCIS magen til en label i pascal (Ikke at forveksle med TLabel) add eax, [edx + 4*ecx] //En integer fylder 4 BYTE (32 bit) så hvis vi skal have fat i Et eller andet element i vores //Buffer array ligger det på adressen Starten af array + (4*Nummeret på elementet) //Adressen på starten af arrayet ligger i edx registeret. Vores tæller variabel er ecx så //regnestykket hedder edx + 4*ecx. Da vi ikke skal have adressen men der der ligger på adressen //stopper vi det hele ind i []. Det hele bliver stoppet over i eax. inc ecx //tæl ecx op med 1 (inc er en forkortelse af increase) cmp ecx, fsize //sammenlign (cmp er en forkortelse af compare) jl @again //hvis ecx < fsize så goto again lablen vi satte før (jl er en forkortelse af Jump less) mov @result, eax //kom resultater af vores tællen sammen over i result end; end;
Hmm .... Jens, har du prøvet dit eksempel? Jeg har lidt problemer med at få koden til at identificere forskelle. Jeg har lavet 2 sprit nye applilationer i Delphi. I den ene er der en knap med en caption := button1 og i det andet med button caption := button2. Programmet beregner identiske checksummer for programmerne, selvom de er forskellige :/
Funktionen GetCheckSum laver kun checksum på max. 500 bytes midt i filen. Det er en meget hurtig måde at gøre det på, men langt fra nøjagtig så vidt jeg kan se.
Du er nødt til at sammenligne hver eneste byte i de to filer for at være sikker, og så er det at starte med en sammenligning på filstørrelser kan spare en bunke tid, især hvis det er store filer.
prøv den her : Function GetCheckSum ( FileName : String) : Integer; var MemoryStream : TMemoryStream; FSize : Integer; P : PChar; begin MemoryStream := TMemoryStream.Create; MemoryStream.LoadFromFile(FileName); p := MemoryStream.Memory; Result := 0; {$R-} for FSize := 0 to MemoryStream.Size do Result := Result + Integer(p[FSize]); {$R+} MemoryStream.Free; end;
Kræver dog minst D5 ellers kan du risikere at få en range check error.
Ok, jeg sammenligner størrelsen. De er ens. Og hvad så, lad os sige, at der kun er ændret en byte i enden af programmet, der fylder 1 mb. Så er det hverken størrelse eller 500 byte i midten der er ændret.
den her er lidt hurtigere : Function GetCheckSum ( FileName : String) : Integer; var MemoryStream : TMemoryStream; i, FSize : Integer; P : PChar; begin MemoryStream := TMemoryStream.Create; MemoryStream.LoadFromFile(FileName); p := MemoryStream.Memory; Result := 0; FSize := MemoryStream.Size div 4; {$R-} for i := 0 to FSize do inc(Result, Integer(p[FSize])); {$R+} MemoryStream.Free; end;
Øøøh ja det er også en fejl ... Det er sq da godt i er vårne .. DEet var fordi jeg var ved at ekpermentere med noget andet : Noget ASM.
Vi bringer lige en opdatering :
Function GetCheckSum (FileName : String) : Integer; var MemoryStream : TMemoryStream; i, FSize : Integer; P : PChar; begin MemoryStream := TMemoryStream.Create; MemoryStream.LoadFromFile(FileName); p := MemoryStream.Memory; Result := 0; FSize := MemoryStream.Size -1; {$R-} for i := 0 to FSize do inc(Result, Integer(p[FSize])); {$R+} MemoryStream.Free; end;
Filerne varierer fra nogle få kb til op til 10 mb. Sammenligningen kommer nu til at køre på en server med adskillige GB ram og RAID, så det kommer ikk til at betyde noget .... så længe der ikke er leaks ;-)
Nej, ellers tak. Sammenligningen af filerne skal jeg bruge i en natlig bygning af omkring 300 dller og exefiler og derudfra bestemme, om der skal incrementeres i en efterfølgende versionsstempling. Så denne sammenligning sker afhængig af en tidsevent
Her er mit bud på hvordan den funktion skal de ud :o) (jeg kunne ikke lade være)
type TFileCompareResult = (fcrEqual, fcrDiferentSizes, fcrDifferentContent, fcrFileNotFound, fcrUnknownError);
function IsSameFile(File1, File2: string): TFileCompareResult; const BUFLEN = 65536; var F1, F2 : file; Buf1, Buf2 : array[0..BUFLEN-1] of byte; Bytes : integer; begin try if (FileExists(File1) and FileExists(File2)) then begin AssignFile(F1, File1); AssignFile(F2, File2); Reset(F1, 1); Reset(F2, 1); if FileSize(F1) = FileSize(F2) then begin Result := fcrEqual; while not Eof(F1) do begin BlockRead(F1, Buf1[0], BUFLEN, Bytes); BlockRead(F2, Buf2[0], BUFLEN, Bytes); if not CompareMem(@Buf1[0], @Buf2[0], Bytes) then begin Result := fcrDifferentContent; break; end; end; end else begin Result := fcrDiferentSizes; end; CloseFile(F1); CloseFile(F2); end else begin Result := fcrFileNotFound; end; except on e: exception do begin MessageBox(0, pchar(E.Message), 'ok', mb_ok); Result := fcrUnknownError; end; end; end;
type TFileCompareResult = (fcrEqual, fcrDiferentSizes, fcrDifferentContent, fcrUnknownError);
function IsSameFile(File1, File2: string): TFileCompareResult; var Stream1, Stream2 : TMemoryStream; begin try Stream1 := TMemoryStream.Create; Stream2 := TMemoryStream.Create; try Stream1.LoadFromFile(File1); Stream2.LoadFromFile(File2);
if Stream1.Size = Stream2.Size then if CompareMem(Stream1.Memory, Stream2.Memory, Stream1.Size) then Result := fcrEqual else Result := fcrDifferentContent else Result := fcrDiferentSizes;
finally Stream1.Free; Stream2.Free; end; except Result := fcrUnknownError; end; end;
Det går nu ikke hurtigere fordi du bruger en stream, det skal loades alligevel, og ulempen ved det ovenstående er du loader hele filen på en gang, det giver et stort ram forbrug.
ja forskellen er at jeg tilgår HD' en gang pr fil. Du til går den flere gange. Det er det der er min pointer, og derfor jeg påstår at mine streams er hurtigere.
Jeg lavede lige en speedtest, på 1MB fil gik det ca. 2-3 gange så langsomt at bruge en stream, som selv at læse med BlockRead.
Synes godt om
Ny brugerNybegynder
Din løsning...
Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.