Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   [Gelöst] mit (Delphi)-ZLib PKZIP/WindowsArchive entpacken (https://www.delphipraxis.net/153986-%5Bgeloest%5D-mit-delphi-zlib-pkzip-windowsarchive-entpacken.html)

Satty67 24. Aug 2010 07:41


[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

gammatester 24. Aug 2010 08:39

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 derzlib-Spezifikation beschrieben) reinfütterst, solltest Du damit keine Probleme mehr haben.

Wenn Du diesen Weg gehen willst, sollte ein Suche einige Delphi-Units finden.

himitsu 24. Aug 2010 08:52

AW: Problem: mit ZLib PKZIP/WindowsArchive entpacken
 
Du kannst den Prüfwert doch immernoch selber generieren, am Anfang einfügen und dann entpacken.

Satty67 24. Aug 2010 09:00

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.

himitsu 24. Aug 2010 09:41

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.

hathor 24. Aug 2010 09:59

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?

Satty67 24. Aug 2010 10:55

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:
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;
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.

@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 11:02 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz