Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   Delphi Dekomprimierung eines Streams (https://www.delphipraxis.net/139097-dekomprimierung-eines-streams.html)

GreenHorn3600 23. Aug 2009 15:59


Dekomprimierung eines Streams
 
Hallo Wissende,

ich bin mal wieder am verzweifeln. Weshalb lässt sich der Stream nicht dekomprimieren?

Delphi-Quellcode:
{Dekompremiert den Stream}
procedure DecrompressStream(aStream: TStream);
var
  zc: TDecompressionStream;
  ms: TMemoryStream;
begin
  ms := TMemoryStream.Create;
  try
   zc := TDecompressionStream.Create(aStream);
   try
      ms.CopyFrom(zc, 0);
    finally
      zc.Free;
    end;
    aStream.Size := 0;
    aStream.copyFrom(ms, 0); //<< Hier kommt der Fehler
  finally
    ms.Free;
  end;
end;
Er bringt mir immer den Fehlercode 5 (System Error, Zugriff verweigert). Nur warum und was kann man gegen tun?

Edit: Es handelt sich mal wieder um die ZLib, Fehlerstelle gekennzeichnet

Grüße
Greeny

himitsu 23. Aug 2009 16:12

Re: Dekomprimierung eines Streams
 
sicher, daß .CopyFrom(..., 0) korrekt so ist?

GreenHorn3600 23. Aug 2009 16:25

Re: Dekomprimierung eines Streams
 
Sicher? Zwischenzeitlich nicht mehr...

aber der Fehler kommt hier:

Delphi-Quellcode:
aStream.Size := 0;
scheint also nicht wirklich damit zusammenzuhängen :|

himitsu 23. Aug 2009 16:48

Re: Dekomprimierung eines Streams
 
was ist denn in aStream für ein Stream drinnen?
nicht jeder StreamTyp unterstützt alle Befehle

[add]
und wegen der 0 in CopyFrom ... da gibt man Count an, also die Anzahl der zu kopierenden Bytes ... bei dir also NICHTS

GreenHorn3600 23. Aug 2009 16:50

Re: Dekomprimierung eines Streams
 
Hallo,

dies ist ein TFileStream, welcher einen zuvor Komprimierten Stream enthält. Dieser soll wieder DeKomprimiert und verarbeitet werden. Daher auch die ganze hin- und herkompiererei.

Igendwo, scheint der Wurm drin zu sein.

GreenHorn3600 23. Aug 2009 16:51

Re: Dekomprimierung eines Streams
 
Zitat:

Zitat von himitsu
[add]
und wegen der 0 in CopyFrom ... da gibt man Count an, also die Anzahl der zu kopierenden Bytes ... bei dir also NICHTS

stimmt nicht ganz, wenn hier bei .copyFrom(..., 0) angegeben ist, so wird intern die Position und die Größe gesetzt. Ist eine Erleichterung.

Ups, Fehlerstelle falsch markiert: hier kommt er aStream.Size := 0; also eine Zeile früher. Das kommt davon, wenn man ständig am kämpfen ist

himitsu 23. Aug 2009 16:58

Re: Dekomprimierung eines Streams
 
ok, dann arbeite ich wohl zu selten mit Stream :oops: (dachte das war bei -1)

ja, wie gesagt, was für einen Stream übergibst du denn nun der Prozedur?

GreenHorn3600 23. Aug 2009 17:01

Re: Dekomprimierung eines Streams
 
Zitat:

Zitat von GreenHorn3600
Hallo,

dies ist ein TFileStream, welcher einen zuvor Komprimierten Stream enthält. Dieser soll wieder DeKomprimiert und verarbeitet werden. Daher auch die ganze hin- und herkompiererei.

Igendwo, scheint der Wurm drin zu sein.


Was soll ich da erst sagen, Streams brauchte ich bisher noch nie, nur dieses mal, komme ich irgendwie nicht dran vorbei :|

turboPASCAL 23. Aug 2009 17:14

Re: Dekomprimierung eines Streams
 
Hilft das? http://www.delphipraxis.net/internal...=480137#480137

himitsu 23. Aug 2009 17:21

Re: Dekomprimierung eines Streams
 
gibt TDecompressionStream den aStream vielleicht frei?
:gruebel:

ich hab es jetzt mal so versucht unb scheitere schon beim 1. CopyFrom, also beim Komprimieren

Delphi-Quellcode:
program Project1;

{$APPTYPE CONSOLE}

uses
  SysUtils, Classes, ZLib;

{Dekompremiert den Stream}
procedure DecompressStream(aStream: TStream);
var
  zc: TDecompressionStream;
  ms: TMemoryStream;
begin
  ms := TMemoryStream.Create;
  try
   zc := TDecompressionStream.Create(aStream);
   try
      ms.CopyFrom(zc, 0);
    finally
      zc.Free;
    end;
    aStream.Size := 0;
    aStream.CopyFrom(ms, 0);
  finally
    ms.Free;
  end;
end;

{Kompremiert den Stream}
procedure CompressStream(aStream: TStream);
var
  zc: TCompressionStream;
  ms: TMemoryStream;
begin
  ms := TMemoryStream.Create;
  try
    zc := TCompressionStream.Create(clDefault, ms);
    try
      zc.CopyFrom(aStream, 0);
    finally
      zc.Free;
    end;
    aStream.Size := 0;
    aStream.CopyFrom(ms, 0);
  finally
    ms.Free;
  end;
end;

Var
  M: TMemoryStream;

begin
  M := TMemoryStream.Create;
  M.Write(M, 4); // irgendwas einlesen, damit was drin ist
  CompressStream(M);
  DecompressStream(M);
end.
[edit] Fehler im CompressStream behoben (Source und Dest sozusagen vertauscht) geht aber dennoch nicht
[edit2] OK, komprimieren geht nun :-D

Muetze1 23. Aug 2009 17:32

Re: Dekomprimierung eines Streams
 
1. TDecompressionStream gibt den im Constructor angegeben Stream nicht frei.
2. Der Fehler liegt einfach nur daran, dass du den als aStream übergebenen Stream mit TFileStream nur zum Lesen geöffnet hast und nun mit Size := 0 und CopyFrom() beschreiben willst, was dieser (aus verständlichen Gründen) verweigert...

GreenHorn3600 23. Aug 2009 17:34

Re: Dekomprimierung eines Streams
 
So, hab den Fehler nun gefunden. Der Quellstream (Filestream) war nur zum lesen geöffnet.

Delphi-Quellcode:
{Kompremiert den Stream}
PROCEDURE CompressStream(aStream: TStream);
VAR
 {$ifdef VER200} //Delphi 2009
  zc: TZCompressionStream;
 {$else}
  {$ifdef VER180} //Delphi 2006 or Turbo Delphi
   zc: TCompressionStream;
  {$endif}
 {$endif}
  ms: TMemoryStream;
BEGIN
  ms := TMemoryStream.Create;
  TRY
  {$ifdef VER200} //Delphi 2009
   zc := TZCompressionStream.Create(ms, zcMax);
  {$else}
   {$ifdef VER180} //Delphi 2006 or Turbo Delphi
    zc := TCompressionStream.Create(clMax, ms);
   {$endif}
  {$endif}
    TRY
      zc.CopyFrom(aStream, 0);
    FINALLY
      zc.Free;
    END;
    aStream.Size := 0;
    aStream.copyFrom(ms, 0);
  FINALLY
    ms.Free;
  END;
END;

{Dekompremiert den Stream}
PROCEDURE DecrompressStream(aStream: TStream);
VAR
 {$ifdef VER200} //Delphi 2009
  zc: TZDecompressionStream;
 {$else}
  {$ifdef VER180} //Delphi 2006 or Turbo Delphi
   zc: TDecompressionStream;
  {$endif}
 {$endif}
  ms: TMemoryStream;
BEGIN
  ms := TMemoryStream.Create;
  TRY
  {$ifdef VER200} //Delphi 2009
   zc := TZDecompressionStream.Create(aStream);
  {$else}
   {$ifdef VER180} //Delphi 2006 or Turbo Delphi
    zc := TDecompressionStream.Create(aStream);
   {$endif}
  {$endif}
    TRY
      ms.CopyFrom(zc, 0);
    FINALLY
      zc.Free;
    END;
    aStream.Size := 0;
    aStream.copyFrom(ms, 0);
  FINALLY
    ms.Free;
  END;
END;
Danke für Eure Hilfe.

Greeny
:cheers: :cheers:

Muetze1 23. Aug 2009 17:39

Re: Dekomprimierung eines Streams
 
Zitat:

Zitat von GreenHorn3600
So, hab den Fehler nun gefunden. Der Quellstream (Filestream) war nur zum lesen geöffnet.

Was man schon im 1. Post an der Meldung des TStreams gesehen hat. Aber die Glaskugeln sind hier wohl alle recht vereicht über die Zeit...

GreenHorn3600 23. Aug 2009 17:42

Re: Dekomprimierung eines Streams
 
Wenn man schon mal den Fehler hatte, lässt er sich sicher einfach lokalisieren. Aber scheint so, als ob nicht nur meine Glaskugel in den Urlaub ist.

Dank Euch
:cheers: :cheers:

Muetze1 23. Aug 2009 17:45

Re: Dekomprimierung eines Streams
 
Zitat:

Zitat von GreenHorn3600
Wenn man schon mal den Fehler hatte, ...

Hatte ich noch nie, ist aber ein dokumentiertes Verhalten von File Handles des WinAPI und somit von TStream Nachfahren. Ansonsten ist es auch durch den mir bekannten Quellcode von TStream eindeutig, da hier einfach nur eine WinAPI Meldung durchgereicht wird.

himitsu 23. Aug 2009 17:54

Re: Dekomprimierung eines Streams
 
PS: auch ohne es auszuprobieren, bin ich mir sicher, daß es, wenn für deinen QuellCode kein D2006 oder D2009 verwendet wird, es bei zc.CopyFrom(aStream, 0); einen Compilerfehler hageln wird, daß zc unbekannt ist, da es vorher nicht deklariert wurde.

[edit]
ja und nun bin ich mal neugierig, was da bei meinem TestCode falsch lief, da der verwendete MemoryStream ja sozusagen Lese- und Schreibrechte gewären sollte.

GreenHorn3600 23. Aug 2009 18:01

Re: Dekomprimierung eines Streams
 
Hallo himitsu,

da hast Du recht, der Code läuft aktuell nur auf D2006 und D2009. Eine Anpassung überlasse ich gerne den Freiwilligen, welche den WebUpdater verwenden möchten. Da ich mit beiden Entwicklungsumgebungen arbeite, ist es für mich derzeit gut so. Produktiv bin ich nur noch mit D2009 unterwegs.

Schau Dir mal in meinen Post, die Procedure zum Komprimieren eines Streams an. Mir scheint, daß hier (bei deiner Komprimierunsroutine) etwas im argen liegt.

Grüße
Greeny

himitsu 23. Aug 2009 18:05

Re: Dekomprimierung eines Streams
 
Also das Komprimieren hatte ich grad hinbekommen, aber das Dekomprimieren sieht genauso aus, wie bei dir und wie gesagt, ich verwende ja 'nen MemoryStream und da würde ich eigentlich kein Problem bezüglich nur Lesen sehen :gruebel:

Seit wann (Delphiversion) gibt es denn TZCompressionStream?
Anstatt da statisch nur auf die beiden Versionen einzugehn, würde ich einfach ab dieser Version umschalten.

GreenHorn3600 23. Aug 2009 18:15

Re: Dekomprimierung eines Streams
 
hallo himitsu,

wenn ich deinen Kode nehme, den Stream am Schluß wieder freigebe und meine beiden Routinen einsetze, scheint es zu funktionieren.

Wie macht man das denn, für alle Versionen darüber und darunter freizugeben? Ich bin ja nur ein GreenHorn :roll:

Den TZC../TCD.. gibts bei D2009 und dies ist halt meine hauptsächlich verwendete Version. Darunter sind diese nicht zu finden (hab auch nur in D2006 gesucht).

Noch einen schönen Sonntag
Greeny

himitsu 23. Aug 2009 18:19

Re: Dekomprimierung eines Streams
 
hmmm, sehr eigenartig :shock:

seit 'ner ganzen Weile können die Compiler das $IF und somit ist da soetwas möglich
> CompilerVersion ist eine virtuelle Konstante in der Unit System,
> welche aber in Wirklichkeit vom Compiler gesetzt wird
Delphi-Quellcode:
{$if CompilerVersion >= 20.0} // ab Delphi 2009
  zc: TZCompressionStream;
{$else}
  zc: TCompressionStream;
{$ifend}

GreenHorn3600 23. Aug 2009 20:59

Re: Dekomprimierung eines Streams
 
Hallo himitsu,

meinst Du zufällig die RTL-Version? Weiß nicht ob das so direkt abgefragt werden kann, im Kompiler, dafür aber im Kode. Doch wo die Probleme auftreten sind die ZLib und die INDY, da gab es einige Syntaxverwirrungen, was ich da so mitbekommen habe. Denke von daher wäre es wohl das sicherste, wenn die Kollegen /-innen welche die entsprechende Version haben, den 3-Zeiler mit beifügen und ihn auch Grad testen. Dann weiß man, daß es funktioniert. Wenn ich mir bspw. die Inkludes von einigen Frameworks ansehe, dann wird dort versucht über einen halben Meter die Unterscheidung einigermaßen zu egalisieren. Vielleicht kommen wir noch so weit mit dem WUS, aber laß uns doch mal klein anfangen und das ganze zum fliegen bringen :-)

Wird wahrscheinlich noch eine Gaudi, wenn Ansi- und UNI-Code gemischt werden, bei unterschiedlichen Codepage'es. Aber dies würde nur Versionen unterhalb D2009 betreffen, und die wenigsten werden noch damit arbeiten. Ansonsten muß man mal sehen, wie man dies am besten abbildet. Bin schon mal gespannt auf die Lösungsvorschläge (sind ja noch entsprechende Freiwillige gesucht).

Wünsche noch einen schönen Abend
Greeny

himitsu 23. Aug 2009 21:17

Re: Dekomprimierung eines Streams
 
die RTL-Version kann man natürlich auch abfragen, aber ist die Konstante natürlich in der RTL definiert.

man kann übrigens auch sowas machen, wenn man z.B. nicht sicher ist
Delphi-Quellcode:
{$IF Declared(TZCompressionStream)}
  zc: TZCompressionStream;
{$else}
  zc: TCompressionStream;
{$ifend}
(geht nicht nur mit Typen, sondern auch mit Variablen und Konstanten)

alzaimar 24. Aug 2009 07:10

Re: Dekomprimierung eines Streams
 
Ich würde mir einen eigenen TGreenDecompressionStream deklarieren, der dann ein direkter Nachfahre von der jeweiligen Compiler/ZLib-Version ist. Das spart sehr viel $IfDef-Direktiven und ist übersichtlicher. In deinem Code arbeitest Du dann nur mit dem 'TGreenCompressionStream' bzw 'TGreenDecompressionStream'.


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