![]() |
[Gelöst] mit (Delphi)-ZLib PKZIP/WindowsArchive entpacken
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo,
ein paar wichtige Dateien und Ordner habe ich bisher per Batch täglich in einem PKZIP-Archiv gesichert. PKZIP ist ja im Prinzip das gleiche Format, wie Windows komprimierte Ordner und lassen sich ab XP direkt ohne weitere Hilfsmittel öffnen. Zum erstellen der Batch hatte ich ein kleines Programm (das sammelt nur die Dateien und generiert die Strings für die Kommandozeile). Jetzt wollte ich einfach selber die PKZIP-Archive erstellen, wozu ich einfach die Unit ZLib verwende. Abrevia und Co. können das natürlich auch, aber das wäre ja langweilig :wink: Zum Problem: ZLib setzt den komprimierten Daten ein 16bit Prüfwert voran, was beim Schreiben des PKZIP-Archiv einfach weggeschnitten wird. Die Archive können problemlos von Windows oder Archiv-Programmen gelesen und entpackt werde. Nur kann ich nicht mit ZLib entpacken, da mir der 16bit Prüfwert fehlt. Wäre er am Ende, würde ich ihn selber generieren und an den Stream anhängen. Hat jemand eine Idee, wie ich mit ZLib dekomprimieren kann, ohne den 16bit Prüfwert? In der ZLib Unit konnte ich keinen Weg finden, das zu Umgehen. Der relevante Code liegt wohl in den OBJ-Dateien. Zum spielen ein kleines Testprogramm in der Anlage |
AW: Problem: mit ZLib PKZIP/WindowsArchive entpacken
Wenn Du von zlib redest, meinst Du die Unit zlib, die von Borland oder wem auch immer als Unit für die zlib-Bibliothek angepriesen wird?
Die richtige zlib-Bibliothek verwendet nämlich keinen 16-Bit-Prüfprefix sondern eine 32-Bit-Adler-Checksumme am Ende. Wenn Du in die richtigen zlib-Routine einen zlib-Stream (wie in Punkt 2.2 der ![]() Wenn Du diesen Weg gehen willst, sollte ein Suche einige Delphi-Units finden. |
AW: Problem: mit ZLib PKZIP/WindowsArchive entpacken
Du kannst den Prüfwert doch immernoch selber generieren, am Anfang einfügen und dann entpacken.
|
AW: Problem: mit ZLib PKZIP/WindowsArchive entpacken
Ja, hatte oben ja angedeutet, dass mir die fertigen Units/Komponenten/Dlls bekannt sind. Es ist auch kein Problem für mich, mit entsprechenden "fremden" Hilfsmitteln PKZIP-Archive zu entpacken.
Nur suche ich im Moment eine Lösung für Delphis-ZLib Unit. Ich bräuchte quasi eine Lösung mit möglichst wenig Fremdcode für ein anderes Projekt (das oben erwähnte Mini-Backup Programm ist dabei quasi nur Test-Platform). @himitsu: Also es ist scheinbar eine Prüfsumme für die entpackten Daten. Die kann ich nicht im Vorfeld mit den gepackten Daten erstellen. |
AW: Problem: mit (Delphi)-ZLib PKZIP/WindowsArchive entpacken
Hmmmmmm, du könntest in den Zipdateikommentaren oder in einer Extradatei in der ZIP diese Prüfzumen ablegen.
Ich weiß auch nicht, ob man sich von der ZLib etwas entpackenlassen und dabei die Prüfsume ignorieren kann. Eventuell einfach irgendeine Dummyprüfsume einfügen, entpacken und die Fehlermeldung ignorieren. |
AW: Problem: mit (Delphi)-ZLib PKZIP/WindowsArchive entpacken
Nebenbei bemerkt:
Hat ein ZIP-File nicht eine maximale Größe von 2 GB? Welches Fileformat wäre besser? 7zip? |
AW: Problem: mit (Delphi)-ZLib PKZIP/WindowsArchive entpacken
Jain, der PKZIP-Header kommt mit 4 GByte klar, aber das reicht auch.
Bin der Sache näher gekomen, die vorangestellten Bytes scheinen doch reproduzierbar. Hatte vorher immer mit der gleichen Quelle gestestet, weshalb mir nicht aufgefallen ist, was mit der neuen Testumgebung auffällt: Mini-Testumgebung (3x Memo, 2x Button, 1x Label, ZipDataStream als Form-Member)
Delphi-Quellcode:
Sowohl bei Delphi 5 als auch bei Delphi 2007 haben die beiden Bytes den Hex-Wert 78 9C. Sorry, dass mir das vorher nicht aufgefallen ist.... damit sollte sich das Problem lösen lassen.
procedure TForm1.FormCreate(Sender: TObject);
begin ZipDataStream := TMemoryStream.Create(); end; procedure TForm1.FormDestroy(Sender: TObject); begin ZipDataStream.Free; end; procedure TForm1.ButtonCompressClick(Sender: TObject); var CompStream : ZLib.TCompressionStream; SourceStream : TStringStream; SourceSize : Integer; b : Byte; begin ZipDataStream.Size := 0; SourceStream := TStringStream.Create(Memo1.Text); SourceSize := SourceStream.Size; CompStream := ZLib.TCompressionStream.Create(clDefault, ZipDataStream); try CompStream.CopyFrom(SourceStream, 0); finally CompStream.Free; SourceStream.Free; end; Label1.Caption := Format('%d Bytes komprimiert zu %d Bytes.', [SourceSize, ZipDataStream.Size]); ZipDataStream.Position := 0; memo2.clear; while ZipDataStream.Read(b, 1) = 1 do memo2.Text := memo2.Text + IntToHex(b,2) +' '; end; procedure TForm1.ButtonDecompressClick(Sender: TObject); var DeCompStream : ZLib.TDeCompressionStream; TargetStream : TStringStream; s : String; c : AnsiChar; begin ZipDataStream.Position := 0; TargetStream := TStringStream.Create(''); DeCompStream := ZLib.TDeCompressionStream.Create(ZipDataStream); try s := ''; while DeCompStream.Read(c, SizeOf(c)) = SizeOf(c) do s := s + c; Memo3.Text := s; finally DeCompStream.Free; TargetStream.Free; end; end; @himitsu Deine erste Lösung war schon die richtige, hatte die nur verworfen, weil ich annahm es ist eine Prüfsumme. Ist aber wohl nur ein magic-Header. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 04:44 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz