Delphi-PRAXiS

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.

Muetze1 26. Mär 2007 18:36

Re: String mit gzip (ent)zippen
 
Memo.Text kannst du der Funktion nicht übergeben, da es eine Property ist. Damit können dahinter Getter/Setter liegen (was hierbei auch der Fall ist) und der Funktion als Stringspeicherplatz eine Methode bzw. deren Code zu geben ist nicht vorteilhaft. Du musst mit Zwischenwerten als Strings arbeiten oder du nutzt den Delphi-Referenz durchsuchenTStringStream.

MatthiasR 19. Mär 2009 10:30

Re: String mit gzip (ent)zippen
 
Liste der Anhänge anzeigen (Anzahl: 2)
2 Jahre sind vergangen und ich stehe wieder vor demselben Problem. Ich lese über ein Kartenterminal Daten von einer Smartcard ein (der eGK, wenns jemanden interessiert :wink: ), von denen es heißt, es handele sich um "gezippte XML-Dateien". "Die Basis für das Zippen ist die Software "gzip"."

Mit den bisher in diesem Thread genannten Lösungsansätzen hatte ich irgendwie kein Glück, bei der ZLib-Funktion erhalte ich wieder den Fehler "Ungültige Zeigeroperation". Ich habe auch schon die ZLib von hier ausprobiert und den Beispielcode auf meine Zwecke abgeändert, aber auch da erhalte ich einen Fehler.

Frage: gibt es irgendwo ein kleines Tool, das mir einen komprimierten String entpackt und anzeigt, damit ich sehen kann, ob die Daten, die ich versuche zu entpacken, überhaupt valide sind? Ich habe die gezippten Strings mal als txt-Dateien unten angehängt, vielleicht kann ja einer von euch mal sein Glück versuchen? Die Standard-Entpack-Programme erwarten solche Daten ja in einem entsprechenden Archiv mit Dateiheader usw. die bringen mich da wohl nicht wirklich weiter.

Vielen Dank schonmal im Voraus!

gammatester 19. Mär 2009 11:44

Re: String mit gzip (ent)zippen
 
Das sind keine gültigen gzip-Files gemäß gzip-spec, denn sie beginnen nicht mit $1f $8b, obwohl diese beiden gzip-ID-Bytes ziemlich am Anfang der Dateien zu finden sind.

Was bedeutet denn genau:
Zitat:

"Die Basis für das Zippen ist die Software "gzip"."
Sieht nach stiller Postaus: ich kenne jemanden, dessen Berater ziemlich sicher ist, einen Programmierer zu kennen, der gehört hat, daß das gzip ist.

Selbst wenn man die Bytes vor den ID-Bytes löscht, kommt nichts Gültiges raus, auch zpipe kommt nicht damit zurecht.

Gammatester

MatthiasR 19. Mär 2009 13:22

Re: String mit gzip (ent)zippen
 
Zitat:

Zitat von gammatester
Was bedeutet denn genau:
Zitat:

"Die Basis für das Zippen ist die Software "gzip"."
Sieht nach stiller Postaus: ich kenne jemanden, dessen Berater ziemlich sicher ist, einen Programmierer zu kennen, der gehört hat, daß das gzip ist.

Die Formulierung stammt aus der Beschreibung des Kartenterminal-Hertstellers, wie die Daten von der Smartcard auszulesen sind. Und sie ist in der Tat nicht wirklich aussagekräftig, daher habe ich sie auch einfach nur im O-Ton wiedergegeben.

Danke dass du dir die Mühe gemacht hast, die Dateien mal etwas unter die Lupe zu nehmen. Ich sehe dadurch nun zwei Möglichkeiten:

1. Was ich von der Karte ausgelesen habe, war schlichtweg Murks, der sich gar nicht erst dekomprimieren lässt.

2. Was ich von der Karte ausgelesen habe, war KEIN Murks, bedarf aber vor dem Dekomprimieren noch einer (oder diverser) Überarbeitung(en), wie Header abschneiden, Trailer abschneiden, mit 4711 multiplizieren oder weiß der Teufel.

3. Der Karteninhalt ist unbrauchbar, was ich aber bereits ausschließen kann, da das Kartenterminal auf seinem eingebauten Display bereits einige Daten der Karte anzeigen kann. Es muss es also selbst bereits geschafft haben, sie korrekt zu lesen und die Daten zu dekomprimieren.

Ich habe auch mal den Kartenterminal-Hersteller kontaktiert, ob die mir da weiterhelfen können. Vielleicht sehen die den Fehler auf Anhieb...

MatthiasR 23. Mär 2009 09:01

Re: String mit gzip (ent)zippen
 
Liste der Anhänge anzeigen (Anzahl: 1)
Also: wie gammatester und ich eindeutig festgestellt haben, handelt es sich bei den von mir ausgelesenen Daten um valide gzip-Konstrukte, lediglich mit einem zusätzlichen Header vor dem gzip-Header '0x1F8B08'. Schneidet man diesen ab und speichert den verbleibenden String in einer Datei mit Endung ".gz", so kann man diese z.B. mittels 7zip entpacken.

Allerdings habe ich es immernoch nicht hingekriegt, den resultierenden gzip-String in meiner Anwendung mittels ZLib zu entpacken.

Der von himitsu gepostete Algorithmus
Delphi-Quellcode:
Uses ZLib;

Function CompressString(Input: String): String;
  Var Buffer: Pointer;
    BufSize: Integer;

  Begin
    Buffer := nil;
    Try
      CompressBuf(Input[1], Length(Input), Buffer, BufSize);
      SetLength(Result, BufSize);
      Move(Buffer^, Result[1], BufSize);
    Finally
      If Buffer <> nil Then FreeMem(Buffer);
    End;
  End;

Function DeCompressString(Input: String): String;
  Var Buffer: Pointer;
    BufSize: Integer;

  Begin
    Buffer := nil;
    Try
      DeCompressBuf(Input[1], Length(Input), 0, Buffer, BufSize);
      SetLength(Result, BufSize);
      Move(Buffer^, Result[1], BufSize);
    Finally
      If Buffer <> nil Then FreeMem(Buffer);
    End;
  End;
liefert mir bei DeCompressBuf immer eine ungültige Zeigeroperation. Was mache ich nur falsch???

Anbei noch die "richtigen" gzip-Dateien, vielleicht kann einer von euch nochmal sein Glück versuchen?!?

PS: Die resultierenden Daten sind reine Testdaten einer fiktiven Person, falls sich jemand Sorgen bezüglich des Datenschutz machen sollte :wink: .

Assertor 29. Mär 2009 21:32

Re: String mit gzip (ent)zippen
 
Hi,

es gibt ein Update für zLibEx, welches nun nativ mit GZip umgehen kann (zLibExGZ). Vielleicht hilft das weiter.

Gruß Assertor

MatthiasR 31. Mär 2009 15:10

Re: String mit gzip (ent)zippen
 
Habe ich gerade mal ausprobiert. Die Funktionen
Delphi-Quellcode:
{*****************************************************************************
*  GZDecompressStr                                                          *
*                                                                            *
*  pre-conditions                                                           *
*    s = compressed data string in gzip format                              *
*                                                                            *
*  post-conditions                                                          *
*    fileName  = filename                                                  *
*    comment   = comment                                                   *
*    dateTime  = date/time                                                 *
*                                                                            *
*  return                                                                   *
*    uncompressed data string                                               *
*****************************************************************************}

function GZDecompressStr(const s: AnsiString; var fileName,
  comment: AnsiString; var dateTime: TDateTime): String; overload;

function GZDecompressStr(const s: AnsiString): String; overload;
sollten ja eigentlich genau dafür gedacht sein, einen string im gzip-Format zu entpacken. Ich bekomme jedoch immer einen "data error", keinen blassen Schimmer, warum das nicht klappt. Ich übergebe die komprimierten Daten ab dem gzip-Header "#$1F#$8B" bis zum Ende der Daten (incl. der ganzen Nullen am Schluss).

Assertor 31. Mär 2009 16:08

Re: String mit gzip (ent)zippen
 
Hi Infect,

Zitat:

Zitat von Infect
function GZDecompressStr(const s: AnsiString; var fileName,
comment: AnsiString; var dateTime: TDateTime): String; overload;

function GZDecompressStr(const s: AnsiString): String; overload;[/delphi]
sollten ja eigentlich genau dafür gedacht sein, einen string im gzip-Format zu entpacken.

Das ist schonmal verkehrt. Du arbeitest mit Binärdaten, wenn Du die in einen AnsiString packen willst, muß Du bezüglich Codepages und automatischer Konvertierung (aka D2009) aufpassen.

Zitat:

Zitat von Infect
Ich bekomme jedoch immer einen "data error", keinen blassen Schimmer, warum das nicht klappt. Ich übergebe die komprimierten Daten ab dem gzip-Header "#$1F#$8B" bis zum Ende der Daten (incl. der ganzen Nullen am Schluss).

Ja, nimm doch mal einen Stream stattdessen. Gerade mit Deinen Rohdaten getestet, geht einwandfrei...

Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
var
  InStream,
  OutStream: TMemoryStream;
begin
  InStream := TMemoryStream.Create;
  OutStream := TMemoryStream.Create;
  try
    InStream.LoadFromFile('D:\Downloads\VersichertenDaten.gz');
    InStream.Position := 0;
    GZDecompressStream(InStream, OutStream);
    OutStream.Position := 0;
    mmo1.Lines.LoadFromStream(OutStream); // mmo1 ist ein Memo auf dem Testform
  finally
    OutStream.Free;
    InStream.Free;
  end;
end;
Das ging jetzt aber in den Bereich "Grundlagen" von Delphi und hat wenig mit gzip zu tun ;)

Gruß Assertor

MatthiasR 1. Apr 2009 10:42

Re: String mit gzip (ent)zippen
 
Also zu allererstmal die Frohebotschaft, dass es nun endlich funktioniert! Ich habe vorher immer mit dem TStringStream gearbeitet, statt TMemoryStream, und das hat irgendwie nicht so funktioniert, wie ich mir das vorgestellt habe. Aber so, wie du es beschrieben hast, klappt es auch bei mir.

Nun aber zum Thema AnsiString und Binärdaten etc.: wenn das ganze Probleme mit Codepages usw. geben kann, wieso arbeiten dann die entsprechenden Kompressionsfunktionen mit den gleichen Datentypen?
Delphi-Quellcode:
{*****************************************************************************
*  GZCompressStr                                                            *
*                                                                            *
*  pre-conditions                                                           *
*    s         = uncompressed data string                                  *
*    fileName  = filename                                                  *
*    comment   = comment                                                   *
*    dateTime  = date/time                                                 *
*                                                                            *
*  return                                                                   *
*    compressed data string in gzip format                                  *
*****************************************************************************}

function GZCompressStr(const s: String; const fileName,
  comment: AnsiString; dateTime: TDateTime): AnsiString; overload;

function GZCompressStr(const s: String): AnsiString; overload;
Es wird ein ganz normaler String übergeben, der mit gzip komprimiert werden soll, und man erhält anschließend einen komprimierten AnsiString im gzip-Format, der ja auch nichts anderes als Binärdaten enthält, oder?!? Wo liegt der Denkfehler?

Aber erstmal Danke, dass du mir da auf die Sprünge geholfen hast, nun geht es endlich so, wie ich mir das vorgestellt habe!!!

Assertor 1. Apr 2009 11:37

Re: String mit gzip (ent)zippen
 
Hi Infect,

Zitat:

Zitat von Infect
Also zu allererstmal die Frohebotschaft, dass es nun endlich funktioniert! [...]
Aber so, wie du es beschrieben hast, klappt es auch bei mir.
[...]
Aber erstmal Danke, dass du mir da auf die Sprünge geholfen hast, nun geht es endlich so, wie ich mir das vorgestellt habe!!!

Das freut mich :)

Zitat:

Zitat von Infect
Nun aber zum Thema AnsiString und Binärdaten etc.: wenn das ganze Probleme mit Codepages usw. geben kann, wieso arbeiten dann die entsprechenden Kompressionsfunktionen mit den gleichen Datentypen?

[...]

Es wird ein ganz normaler String übergeben, der mit gzip komprimiert werden soll, und man erhält anschließend einen komprimierten AnsiString im gzip-Format, der ja auch nichts anderes als Binärdaten enthält, oder?!? Wo liegt der Denkfehler?

Ja, die Funktionen sind auch richtig - es lassen sich ja auch prinzipiell Binärdaten in AnsiStrings erfassen.

Das Probleme ist aber: Wie bekommst Du die Daten unverändert in und aus dem String.

In Delphi 2009 wurde deswegen der RawByteString eingeführt, damit unter keinen Umständen Veränderungen am String durchgeführt werden. Dies erfolgt im Hintergrund durch die Festlegung der CodePage auf:

Delphi-Quellcode:
type
  RawbyteString = type AnsiString($ffff);
Genau darin liegt/lag aber das Problem von manchem Code vor Delphi 2009: Der AnsiString wurde zum Speichern von Daten verwendet, was sich bei der Umstellung von Source und Komponenten in Delphi 2009 rächte. Zwei Hauptprobleme dabei sind: 1) Konvertierung zur Laufzeit / Compiler-Magic und 2) die Länge von Chars (wegen der damalig festen Annahme von 1 Char = 1 Byte).

Bei jeder Zuweisung eines AnsiString kannst Du nicht sicher sein, daß die CodePage nicht abweicht und somit eine Konvertierung des Strings durchgeführt wird. Wenn der String nun Daten hält, werden diese ungültig.

Wenn Du, wie in meinem Beispielcode, direkt am Stream arbeitest umgehst Du diese Probleme.

Natürlich kannst Du auch eine Funktion schreiben, die die Daten in einem AnsiString/RawByteString einliest und dann die zLib Funktionen für AnsiStrings verwenden. Aber da wären einige Sachen wegen oben genannter Probleme zu beachten.

Gruß Assertor

MatthiasR 1. Apr 2009 14:59

Re: String mit gzip (ent)zippen
 
Liste der Anhänge anzeigen (Anzahl: 1)
Danke für die Aufklärung! Auch wenn ich ehrlich gesagt nicht alles 100%ig verstanden habe, so sehe ich ein, dass das ganze sehr fehlerträchtig ist. Daher habe ich nun meine Anwendung auf Streams umgestellt und an sich funktioniert alles bestens, nur habe ich jetzt ein neues Problem (ich könnte echt druchdrehen!):

In einem weiteren gzip-komprimierten String-Container wurden zwei XML-Konstrukte unmittelbar hintereinander gehängt. Und zwar in dieser Art:
Zitat:

<?xml version="1.0" encoding="ISO-8859-15"?>
<Dokument1>
...
</Dokument1>
<?xml version="1.0" encoding="ISO-8859-15"?>
<Dokument2>
...
</Dokument2>
Dekomprimiere ich diese gzip-Datei mittels 7zip, so erhalte ich das doppelte XML-Konstrukt so wie erwartet. Lasse ich jedoch die Funktion "GZDecompressStream(InputStream, OutputStream)" darauf los, so erhalte ich als Ergebnis lediglich den ersten Teil. Alles ab dem zweiten XML-Header fehlt!

Woran liegt das denn nun schon wieder???

Probier es selbst mal aus, ich hab dir eine entsprechende Datei mal angehängt.

gammatester 1. Apr 2009 17:05

Re: String mit gzip (ent)zippen
 
Mit meinen gzio-Routinen funktioniert's. Vielleicht ein Bug in DelphiZLib.123?

Gruß Gammatester

MatthiasR 2. Apr 2009 07:27

Re: String mit gzip (ent)zippen
 
Da hast du recht, über deine gzio-Unit hat das ganze funktioniert. Da ich aber ungern über den Umweg einer Datei arbeiten will, würde ich gerne was anderes dafür verwenden. Deine gzdbuf werde ich nun auch nochmal testen, aber ich muss ehrlich sagen: das Handling der ZLibEx-Units fällt mir persönlich deutlich leichter, da die eben "Delphi-like" sind. Aber ist ja auch kein Wunder, deine Units sollen ja nur ein 1 zu 1 Port der C Routinen (mit gewissen Erweiterungen) sein, wenn ich das richtig verstanden hab.

MatthiasR 2. Apr 2009 08:29

Re: String mit gzip (ent)zippen
 
So, nun habe ich endlich herausgefunden, warum das mit deiner gzdbuf-Unit bisher nicht funktionierte. Ich habe der Funktion gzb_init als Buffer ein dynamisches Array übergeben, kein statissches wie in deinem Beispiel. Und dynamische Arrays beginnen ja mit dem Index 0 und nicht wie bei dir mit 1.

Was müsste ich ändern, damit das ganze auch mit dynamischen Arrays klappt? Auf jeden Fall bin ich nun wieder einen Schritt weiter.

gammatester 2. Apr 2009 08:58

Re: String mit gzip (ent)zippen
 
Zitat:

Zitat von Infect
So, nun habe ich endlich herausgefunden, warum das mit deiner gzdbuf-Unit bisher nicht funktionierte. Ich habe der Funktion gzb_init als Buffer ein dynamisches Array übergeben, kein statissches wie in deinem Beispiel. Und dynamische Arrays beginnen ja mit dem Index 0 und nicht wie bei dir mit 1.

Was müsste ich ändern, damit das ganze auch mit dynamischen Arrays klappt? Auf jeden Fall bin ich nun wieder einen Schritt weiter.

Hier das angepaßte Demoprogramm für vsd.gz, der interessante Teil sollte unabhängig von dynamisch/statissch sein, wenn Dein Puffer mit Index 0 beginnt.

Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
var
  ibuf: array of byte;
  f: file;
  gz: gzbuf;
  i: integer;
  s: string;
begin
  assignfile(f,'vsd.gz');
  system.reset(f,1);
  setlength(ibuf,5000);
  blockread(f,ibuf[0],1242);
  gz := gzb_init(pBytef(@ibuf[0]),1242); // dies ist der interessante Teil
  s := '';
  while not gzb_eof(gz) do begin
    i := gzb_getc(gz);
    if i<0 then break;
    if (i>0) and (i<256) then s := s+char(i);
  end;
  richedit1.Text := s;
end;
Gruß Gammatester

MatthiasR 2. Apr 2009 09:22

Re: String mit gzip (ent)zippen
 
:dancer2: Juhu, so funktioniert das ganze! :dancer2:

In deinem Beispielprogramm von letzter Woche sah die Wertüberprüfung von i aber noch so aus:
Delphi-Quellcode:
if (i > 31) and (i < 256) then
Ich vermute mal, du wolltest damit nicht druckbare Steuerzeichen überspringen. Das ist in meinem Fall gewünscht und daher würde ich das so belassen.

Gut, dann hätten wirs ja. Thread darf als gelöst betrachtet werden. Und nochmals danke an alle Beteiligten! :cheers:


Alle Zeitangaben in WEZ +1. Es ist jetzt 11:10 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