Binärvergleich um Patcher zu programmieren?

Für allgemeine Fragen zur Programmierung mit PureBasic.
Benutzeravatar
Proton
Beiträge: 152
Registriert: 20.06.2006 12:21
Wohnort: Eckernförde /Stadtbergen

Beitrag von Proton »

@stbi:
Lesen und verstehen. Ich schrieb: "Wenn es da eine vernünftige Möglichkeit gebe...."

>>>Zu bedenken ist, dass Patchen von Binärdateien nur bei geringen
>>>Änderungen sinnvoll ist, da die komplettee Patchinformation relativ
>>>umfangreich im Verhältnis zur eigentlichen Änderung ist

Was meinst du anderes als ich ?? :| /:->
Zitat:
"Ich kann mich vor die Meute stellen und für Nichts kämpfen. Ich kann aber auch einen Schritt zur Seite gehen, die Meute vorbeiziehen lassen und dabei meine Zeit angenehm bei Freunden verbringen.". Da hat er Recht, mein Pap's.
Kaeru Gaman
Beiträge: 17389
Registriert: 10.11.2004 03:22

Beitrag von Kaeru Gaman »

stbi hat geschrieben:Jeder lahme Autofahrer setzt aus diesem Grund nen Hut auf :D
:lol: :mrgreen: :allright: :twisted:
Der Narr denkt er sei ein weiser Mann.
Der Weise weiß, dass er ein Narr ist.
Benutzeravatar
stbi
Beiträge: 685
Registriert: 31.08.2004 15:39
Wohnort: Cleverly Hills

Beitrag von stbi »

Proton hat geschrieben:Was meinst du anderes als ich ?? :| /:->
1. gebe ich kein pauschales Statement ab
2. nenne ich Quellen für Algos und Software, anstatt viel Erfolg bei der Suche zu wünschen
3. begründe ich mögliche Einschränkungen

Auch wenn Du letztlich nichts anderes meintest als ich, fängt er mit Deinem Statement wohl herzlich wenig an.
PB 4.02 XP Pro SP2 "Der Code ist willig, aber der Prozessor ist schwach."

Es gibt keine Vista-Witze. Es ist alles wahr!
Benutzeravatar
Proton
Beiträge: 152
Registriert: 20.06.2006 12:21
Wohnort: Eckernförde /Stadtbergen

Beitrag von Proton »

Bla
:)
Zitat:
"Ich kann mich vor die Meute stellen und für Nichts kämpfen. Ich kann aber auch einen Schritt zur Seite gehen, die Meute vorbeiziehen lassen und dabei meine Zeit angenehm bei Freunden verbringen.". Da hat er Recht, mein Pap's.
real
Beiträge: 468
Registriert: 05.10.2004 14:43

Beitrag von real »

Bei zwei Dateien ist es ja nicht einfach so, dass Datei1 (alt) einfach an bestimmten Stellen verändert werden muss, um zu Datei2 (neu) zu werden. Was machst Du z.B., wenn Datei1 kleiner/größer als Datei2 ist?

Grds. mein Vorschlag:
Reservieren eines Differenzspeichers im RAM. Grds. Vergleich jedes einzelnen Bytes, unveränderte Bytes werden dabei in der Differenz mit $00 gekennzeichnet. Anschließend Differenz packen und als Datei speichern. $00en dürften recht gut zu packen sein, die Differenzdatei sollte dadurch nicht groß werden, wenn sich die Änderungen in Grenzen halten.

Dabei wird nicht beachtet, was ich oben zur Dateigröße geschrieben hab.
Benutzeravatar
cyan
Beiträge: 24
Registriert: 22.09.2006 16:43
Kontaktdaten:

Beitrag von cyan »

Hallo... dies ist mein erster Post ^^ :mrgreen: :mrgreen:
ich hab mal die Idee von Real aufgegriffen, und daraus 2 Procedures gemacht... funzt auch, wenn die 2 dateien nicht gleich groß sind...

achja, purebasic ist toll ^^

Code: Alles auswählen

;createpatch(file1.s,file2.s,patchpath.s)
;file1 = Pfad zur alten Version einer Datei
;file2 = Pfad zur neuen Version einer Datei
;Patchpath = Speicherpfad des Patches 

Procedure createpatch(file1.s,file2.s,patchpath.s)
  Protected MemPoint.l = 0 , LenOfFile1.l , LenOfFile2.l
  Protected ByteOld.b , ByteNew.b
  Protected *Data1, *Data2, *Data3
  
  ;Wenn file1 = file2, Prozedure verlassen
  If MD5FileFingerprint(file1) = MD5FileFingerprint(file2)
    ProcedureReturn #False
  EndIf
  
  ReadFile(0,file1)
  ReadFile(1,file2)
  LenOfFile1 = Lof(0)
  LenOfFile2 = Lof(1)
  *Data1 = AllocateMemory(LenOfFile1)
  *Data2 = AllocateMemory(LenOfFile2)
  *Data3 = AllocateMemory(LenOfFile2+33)  ; '+33' für den MD5 Header
  ReadData(0,*Data1,LenOfFile1)
  ReadData(1,*Data2,LenOfFile2)
  
  PokeS(*Data3,MD5FileFingerprint(file1)) ; Speichert MD5Fingerprint
  
  While MemPoint < LenOfFile2
    
    If MemPoint < LenOfFile1
      ByteOld = PeekB(*Data1+MemPoint)
    Else
      ByteOld = 0
    EndIf
    
    ByteNew = PeekB(*Data2+MemPoint)
    
    If ByteOld = ByteNew
      PokeB(*Data3+33+MemPoint,0) ;ja nicht den MD5 Header überschreiben
    Else
      PokeB(*Data3+33+MemPoint,ByteOld-ByteNew)
    EndIf
    
    MemPoint = MemPoint + 1
    
  Wend
  
  CreatePack(patchpath) 
  AddPackMemory(*Data3,LenOfFile2+33,9)
  ClosePack()
  CloseFile(0)  ;keine Ahnung wann man am besten file1 u. file2 closed              
  CloseFile(1)
  FreeMemory(*Data1)
  FreeMemory(*Data2)
  FreeMemory(*Data3)
  ProcedureReturn #True
EndProcedure

Code: Alles auswählen

;patchit(file1.s,pak.s)
;file1 = Pfad zur alten Version einer Datei
;pak = Pfad zum Patch

Procedure patchit(file1.s,pak.s)
  Protected ByteOld.b , ByteDiff.b
  Protected PakMD5.s
  Protected PakSize.l, i.l
  Protected *Patch, *DataFile
  
  OpenPack(pak)
  *Patch = NextPackFile()
  PakSize = PackFileSize()
  PakMD5 =  PeekS(*Patch,32)
  
  If MD5FileFingerprint(file1) <> PakMD5  ;MD5 überprüfen
    ProcedureReturn #False
  EndIf
  
  CopyFile(file1,file1+".backup") ;Backup erstellen
  OpenFile(0,file1)
  
  For i = 33 To PakSize ;Nachdem MD5Header weiterlesen
    FileSeek(0,i-33)
    ByteOld = ReadByte(0)
    ByteDiff = PeekB(*Patch+i)
    FileSeek(0,i-33)
    WriteByte(0,ByteOld-ByteDiff)
  Next i
  
  If (PakSize-33) < Lof(0)  ;Wenn Original-Datei > Update Datei, dann....
    FileSeek(0,0)
    *DataFile = AllocateMemory(PakSize-33)
    ReadData(0,*DataFile,PakSize-33)
    CloseFile(0)
    DeleteFile(file1)
    CreateFile(0,file1)
    WriteData(0,*DataFile,PakSize-33)
  EndIf
  
  CloseFile(0)
  ClosePack()
  FreeMemory(*Patch)
  FreeMemory(*DataFile)
  ProcedureReturn #True
EndProcedure
Benutzeravatar
pvmichael
Beiträge: 144
Registriert: 29.08.2004 17:59
Wohnort: Rosenheim
Kontaktdaten:

Beitrag von pvmichael »

@cyan:

Wow, ich bin begeistert, DANKE!, ein erster Test mit einem Textfile hat wunderbar geklappt, werd es mal mit meinen großen EXEn versuchen :-)
Benutzeravatar
cyan
Beiträge: 24
Registriert: 22.09.2006 16:43
Kontaktdaten:

Beitrag von cyan »

sollte normal gut funktionieren...
ich hab die patchit-prozedur bisschen optimiert, so, dass sie ihre daten im RAM bearbeitet... so ists eindeutig schneller ^^.... falls interesse, bitte melden
Benutzeravatar
pvmichael
Beiträge: 144
Registriert: 29.08.2004 17:59
Wohnort: Rosenheim
Kontaktdaten:

Beitrag von pvmichael »

cyan hat geschrieben:sollte normal gut funktionieren...
ich hab die patchit-prozedur bisschen optimiert, so, dass sie ihre daten im RAM bearbeitet... so ists eindeutig schneller ^^.... falls interesse, bitte melden
Ja, natürlich! Die Dateien mit denen ich es zu tun habe, sind immerhin 200MB groß, da kommst schon auf Geschwindigkeit an :D
Benutzeravatar
cyan
Beiträge: 24
Registriert: 22.09.2006 16:43
Kontaktdaten:

Beitrag von cyan »

bitte schön ^^

Code: Alles auswählen

;patchit(file1.s,pak.s)
;file1 = Pfad zur alten Version einer Datei
;pak = Pfad zum Patch

Procedure patchit(file1.s,pak.s)
  Protected ByteOld.b , ByteDiff.b
  Protected PakMD5.s
  Protected PakSize.l, i.l, lenoffile
  Protected *Patch, *DataFile, *Data2
  
  OpenPack(pak)
  *Patch = NextPackFile()
  PakSize = PackFileSize()
  PakMD5 =  PeekS(*Patch,32)
  
  If MD5FileFingerprint(file1) <> PakMD5
    ProcedureReturn #False
  EndIf
  
  
  CopyFile(file1,file1+".backup")
  ReadFile(0,file1)
  lenoffile = Lof(0)
  *DataFile = AllocateMemory(Lof(0))
  *Data2 = AllocateMemory(PakSize-33)
  ReadData(0,*DataFile,Lof(0))
  CloseFile(0)
  
  For i = 33 To PakSize
    If i-33<lenoffile
      ByteOld = PeekB(*DataFile+i-33)
    Else
      ByteOld = 0
    EndIf
    
    ByteDiff = PeekB(*Patch+i)
    PokeB(*Data2+i-33,ByteOld-ByteDiff)
    
  Next i
  
  
  DeleteFile(file1)
  CreateFile(0,file1)
  WriteData(0,*Data2,PakSize-33)
  CloseFile(0)
  ClosePack()
  FreeMemory(*Patch)
  FreeMemory(*DataFile)
  FreeMemory(*Data2)
  ProcedureReturn #True
EndProcedure
Antworten