Delphi-PRAXiS
Seite 1 von 3  1 23      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi String mit gzip (ent)zippen (https://www.delphipraxis.net/89090-string-mit-gzip-ent-zippen.html)

MatthiasR 26. Mär 2007 08:17


String mit gzip (ent)zippen
 
Hallo miteinander.

Ich stehe vor folgendem "Problem": ich möchte gerne einen einfachen String per gzip zippen bzw. entzippen. Es sollen keine Archive oder so auf Festplatte geschrieben werden, lediglich der gzip-Algorithmus auf einen String im hauptspeicher angewendet werden.

ich habe im Forum schon von der Unit ZLib gelesen und dass die gzip beherrsche. U.a. habe ich folgendes Beispiel gefunden und bereits versucht, auf mein Problem umzubauen:
Delphi-Quellcode:
uses ZLib, SysUtils;
Packen:
procedure Compress(InputFileName, OutputFileName: string);
var InputStream, OutputStream: TFileStream;
  CompressionStream: ZLib.TCompressionStream;
begin
  InputStream:=TFileStream.Create(InputFileName, fmOpenRead);
  try
    OutputStream:=TFileStream.Create(OutputFileName, fmCreate);
    try
      CompressionStream:=TCompressionStream.Create(clMax, OutputStream);
      try
        CompressionStream.CopyFrom(InputStream, InputStream.Size);
      finally
        CompressionStream.Free;
      end;
    finally
      OutputStream.Free;
    end;
  finally
    InputStream.Free;
  end;
end;

Entpacken:
procedure Decompress(InputFileName, OutputFileName: string);
var InputStream, OutputStream: TFileStream;
  DeCompressionStream: ZLib.TDeCompressionStream;
begin
  InputStream:=TFileStream.Create(InputFileName, fmOpenRead);
  try
    OutputStream:=TFileStream.Create(OutputFileName, fmCreate);
    try
      DecompressionStream:=TDecompressionStream.Create(OutputStream);
      try
        DecompressionStream.CopyFrom(InputStream, InputStream.Size);
      finally
        DecompressionStream.Free;
      end;
    finally
      OutputStream.Free;
    end;
  finally
    InputStream.Free;
  end;
end;
Ich habe versucht, statt TFileStream die Klassen TMemoryStream und TStringStream zu verwenden, aber ohne den gewünschten Erfolg. Ich habe es einfach nicht hinbekommen. Außerdem habe ich mich schonmal mit den Abrevia-Komponenten beschäftigt, aber dort auch keine gefunden, die mir lediglich einen Datenstrom im Hauptspeicher zippt, ohne diesen anschließend auf Festplatte schreiben zu wollen. Möglich wäre das zur Not, klar, aber einfach unschön.

Daher meine Fragen:
  • Kann die Unit Zlib auch wirklich mit gzip arbeiten und wie kann ich dies auch wirklich sicherstellen?
  • Kann mir jemand das obige Beispiel so umstellen, dass meine Anforderungen erfüllt werden? Also dass die Funktionen einfach einen String als Input bekommen und den ent-/gezippten String als Output liefern? Eine komplett neue Implementierung wäre natürlich auch willkommen :) .

Vielen lieben Dank schonmal!!!

turboPASCAL 26. Mär 2007 08:41

Re: String mit gzip (ent)zippen
 
ZLib macht gZip ? Nein.

Zitat:

zlib is a free software/open-source, cross-platform data compression library by Jean-loup Gailly and Mark Adler and is an abstraction of the DEFLATE compression algorithm used in their gzip file compression program.
Einen String Compress/decompress Algo (ZLib) findest du hier


PS.: Vill ist es ja auch nicht GZip was deinen Hauptspeicherstring betrifft... :mrgreen:

MatthiasR 26. Mär 2007 09:30

Re: String mit gzip (ent)zippen
 
Zitat:

Zitat von turboPASCAL
ZLib macht gZip ? Nein.

Hier steht aber, ZLib macht gzip, oder hab ich da jetzt irgendwas falsch verstanden? Oder ist gzip keine eigene Zip-Implementierung sondern lediglich ein Programm, das einen andren Zip-Algorithmus benutzt?!?

turboPASCAL 26. Mär 2007 09:55

Re: String mit gzip (ent)zippen
 
Also die normale ZLib-Unit macht kein gZip, in der ZLib.Pas (Version 1.1.3) sind auch keine
Funktionen dazu implementiert.

MatthiasR 26. Mär 2007 14:33

Re: String mit gzip (ent)zippen
 
Habe nun mal die Funktionen aus deinem Link ausprobiert. Ließen sich anfangs nicht kompilieren, weil die darin verwendeten Funktionen CompressBuf und DeCompressBuf als ersten Parameter einen Zeiger erwarten. Habe das "[1]" entfernt und ein "@" vor das Input geschrieben. Dann gings. Ich habe zu Testzwecken dann zwei Memofelder auf ein Formular geklatscht und den Inhalt des einen auf Knopfdruck komprimiert und im andern angezeigt. Hat funktioniert. Daraufhin wollte ich das ganze wieder dekomprimieren und bekam dann die Fehlermeldung "Ungültige Zeigeroperation" in der Funktion DeCompressBuf. Woran kann das liegen? Bin nicht sonderlich zeigerbewandt, nur zur Info :wink: !

Zum Thema ZLib/gzip: sorry, hatte dein zitat von oben nicht aufmerksam genug gelesen :mrgreen: .

Muetze1 26. Mär 2007 14:50

Re: String mit gzip (ent)zippen
 
Zitat:

Zitat von Infect
Habe das "[1]" entfernt und ein "@" vor das Input geschrieben.

Kombiniere beides - also das [1] lassen und davor dann das @, dann sollte es klappen.

MatthiasR 26. Mär 2007 14:58

Re: String mit gzip (ent)zippen
 
Auch das hatte ich schon, aber kommt das Zeigertechnisch nicht aufs selbe raus, ob ich die Adresse des ersten Characters nehme oder die Adresse des kompletten String?

Den Pointerfehler resultiert übrigens wohl daraus, dass ich als Input/Output der Funktionen die Text-Eigenschaft der memos verwendet habe. Da beim Comprimieren Steuerzeichen entstehen, die das memo nicht darstellen kann, tauscht es die Zeichen gegen diese schwarzen Kästchen aus, die wiederum beim Einlesen einen Murks erzeugen. So oder ähnlich :mrgreen: .

himitsu 26. Mär 2007 14:59

Re: String mit gzip (ent)zippen
 
Zitat:

Zitat von Infect
Habe das "[1]" entfernt und ein "@" vor das Input geschrieben. Dann gings.

:shock: *Schock*
Du hast doch als Parameter einen "normalen" String verwendet?

@xyz liefert einen Zeiger auf die stringrefferenz
@xyz[1] zeigt auf das erste Zeichen, also den Stringinhalt
xyz[1] gibt das Zeichen zurück

[edit]
hab ausversehn editiert, statt mich zitiert ... bekomm jetzt den Originalbeitrag nich mehr komplett zusammen :freak:

MatthiasR 26. Mär 2007 15:13

Re: String mit gzip (ent)zippen
 
Zitat:

Zitat von himitsu
@xyz liefert einen Zeiger auf die stringrefferenz
@xyz[1] zeigt auf das erste Zeichen, also den Stringinhalt
xyz[1] gibt das Zeichen zurück

Entsprechen sich die Speicheradressen von xyz und xyz[1], also @xyz und @xyz[1] nicht? "@xyz[1] zeigt auf das erste Zeichen, also den Stringinhalt" habe ich jetzt aber nicht verstanden. Der Stringinhalt besteht doch aus mehreren Zeichen.

EDIT: Auf alle Fälle geht nun alles wie gewünscht. Der Grund für die ungültige Zeigeroperation hat sich bestätigt. Wenn ich den komprimierten String ganz normal als String zwischenspeicher und nicht direkt in die Text-Eigenschaft des Memos klatsche, dann funktionierts.

himitsu 26. Mär 2007 15:54

Re: String mit gzip (ent)zippen
 
Nein, XYZ ist nur ein Zeiger auf einen "Record", wo dann die Stringdaten (Referenzzähler, Längenangabe und der Stringinhalt) drin sind.

sozusagen so:
Delphi-Quellcode:
TAnsiString = Record
  RefCount: Integer;
  Len:     Integer;
  Data:    Array[1..Len+1] of AnsiChar; // +1, da noch ein #0 hinten dran ist
End;

Pointer(xyz) = @TAnsiString.Data
Du kannst es dir wie eine KlassenReferenz vorstellen.

@xyz zeigt also nur auf einen Pointer, wo drin steht an welcher Stelle sich der StringRecord befindet.

"nur" PChar(xyz) und @xyz[1] zeigen also auf den Stringinhalt.


Alle Zeitangaben in WEZ +1. Es ist jetzt 02:30 Uhr.
Seite 1 von 3  1 23      

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