Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   Delphi Komprimiertes Speichern von Virtual Stringtree / Stream (https://www.delphipraxis.net/162221-komprimiertes-speichern-von-virtual-stringtree-stream.html)

friedemann2009 13. Aug 2011 08:57

Komprimiertes Speichern von Virtual Stringtree / Stream
 
Morgen zusammen,

folgendes Problem: Habe eine VST mit SEHR VIELEN Zeilen, die ich via VST.savetostream in einen Filestream speichere. Bei sehr großen Datenmengen wird die gespeicherte Datei allerdings schnell mal 1GB groß = unverhältnismäßig groß für reine Textdaten. Daher habe ich eine bei den Schweizern gefundene Streamkomprimierung eingebaut. Letztere übergibt den komprimierten Stream allerdings an TMemorystream; folglich habe ich VST.savetostream zunächst an TMemorystream übergeben, um es dann zu komprimieren und dann zu speichern (via Umleitung in TFilestream). Leider scheint das speichern der VST-Daten in TMemorystream unendlich viel langsamer zu sein bzw. kommt nie zum Ende; hat jemand eine Ahnung warum bzw. wie ich das umgehen könnte (außer zuerst unkomprimiert in TFilestream zu speichern, dann wieder zu laden, zu komprimieren und wieder zu speichern..)?

Das ist der relevante Code:

Delphi-Quellcode:
uses ZLib;

procedure CompressStream(inpStream, outStream: TStream);
var
  InpBuf, OutBuf: Pointer;
  InpBytes, OutBytes: Integer;
begin
  InpBuf := nil;
  OutBuf := nil;
  try
    GetMem(InpBuf, inpStream.Size);
    inpStream.Position := 0;
    InpBytes := inpStream.Read(InpBuf^, inpStream.Size);
    CompressBuf(InpBuf, InpBytes, OutBuf, OutBytes);
    outStream.Write(OutBuf^, OutBytes);
  finally
    if InpBuf <> nil then FreeMem(InpBuf);
    if OutBuf <> nil then FreeMem(OutBuf);
  end;
end;


procedure TForm1.Button8Click(Sender: TObject);
var
  kompstream: tstream;
  stream: TMemorystream;
begin
  stream:= TMemoryStream.Create;
  kompstream:= TFileStream.Create(savedlg2.filename, fmCreate);
 
  try
    vst.SaveToStream(stream);
    CompressStream(stream, kompstream);
  finally
    stream.free;
    kompstream.Free;
  end;

end;
Danke und Euch allen ein schönes WE,
Frieder

stahli 13. Aug 2011 10:55

AW: Komprimiertes Speichern von Virtual Stringtree / Stream
 
Mit diesen Funktionen arbeite ich problemlos.
Vielleicht findest Du dort einen Anhaltspunkt.

Bernhard Geyer 13. Aug 2011 10:59

AW: Komprimiertes Speichern von Virtual Stringtree / Stream
 
Ich würde hier eher ein generelles Redesign machen und die Datenhaltung einer Embedded/Desktop-DB übergeben. Und im VST werden nur die angezeigten Daten aus der DB geladen.
Damit dürfte bei richtiger Programmierung dein Lade/Speicherperformance-Problem der Vergangenheit angehören.

friedemann2009 14. Aug 2011 07:19

AW: Komprimiertes Speichern von Virtual Stringtree / Stream
 
Moin zusammen,

danke für die Hinweise. Die (De-)Compress-Routinen hatte ich ja bereits, habe es dennoch nochmal damit getestet. Das Problem liegt wohl an anderer Stelle: Mein Prog hängt sich offenbar auf, wenn ich versuche, _sehr große_ Daten via VST.savetostream in ein TMemorystream zu speichern. Offenbar komme ich da an eine Grenze. Wenn ich den VST-Stream direkt an TFileStream übergebe, habe ich das Problem nicht (klar, große Daten brauchen länger, aber es geht doch wesentlich schneller bzw. kommt überhaupt zu einem Ende im Vergleich zu TMemoryStream). - Wie gesagt, wird dann die Datei aber viel zu groß.

- Sehe ich das richtig, wenn ich wohl doch zuerst in TFilestream speichern, dann wieder laden, komprimieren und dann erneut in TFilestream speichern muss (unter Umgehung von TMemoryStream) oder gibt es noch eine andere Möglichkeit, mit der dieses 'Zwischenspeichern' umgehen könnte?

Danke und schönen Samstag,
frieder

Sir Rufo 14. Aug 2011 07:44

AW: Komprimiertes Speichern von Virtual Stringtree / Stream
 
Die Grenze heißt 32-Bit und kann nur 2GB RAM pro Programm verwalten.

Somit wirst du gezwungen sein erst in einen temp. FileStream zu schreiben und dann zu komprimieren.
Oder du erstellst dir eine TFileStream-Ableitung die sofort komprimiert.

himitsu 14. Aug 2011 07:45

AW: Komprimiertes Speichern von Virtual Stringtree / Stream
 
Welche Delphiversion nutzt du eigentlich?

Ich weiß nicht seit wann es den gibt, aber vergiß nicht, daß die vielen Daten, beim TMemorystream erstmal in den Arbeitsspeicher rein müssen.
Bei 1 GB kann es schnell mal eng werden und dann kopiert der auch ständig/öfters seinen Speicher um, um ihn zu vergrößeren.
(eventuell kann es helfen, wenn man den speicher vor SavetoStream über .Size schonmal vorbelegt)

Es gibt da auch Delphi-Referenz durchsuchenTZCompressionStream und Delphi-Referenz durchsuchenTZDecompressionStream in der unit ZLib, diese Stream hängst du direkt an den TFileStream und übergibst sie der Speicherroutine, damit wird direkt komprimiert und gleich abgespeichert ... spart enorm viel an Arbeitsspeicher.


PS: Ein VirtualStringTree ist doch eigentlich dafür gedacht nur "externe" Daten anzuzeigen und nicht um als Datencontainer genutzt zu werden?
Demnach sollte er selber keine Daten besitzen, welche man abspeichern wöllte ... Speichern tut man ja eigentlich die Originaldaten.

PSS:
Zitat:

Delphi-Quellcode:
procedure CompressStream(inpStream, outStream: TStream);

Eigentlich sollten derartige Prozeduren schon fertig in der Unit ZLib rumliegen. (also mindestens seit TDE/D2006)

Sir Rufo 14. Aug 2011 07:51

AW: Komprimiertes Speichern von Virtual Stringtree / Stream
 
Der Punkt ist doch das wir im Speicher Daten rumliegen haben die 1GB groß sind.
Diese kommen jetzt in einen TMemoryStream rein.
Nach meinem Verständnis benötigt das Prog jetzt 2GB RAM.

Und ab da streikt 32-Bit

himitsu 14. Aug 2011 07:54

AW: Komprimiertes Speichern von Virtual Stringtree / Stream
 
Zitat:

Zitat von Sir Rufo (Beitrag 1116725)
Und ab da streikt 32-Bit

Ach, kein Problem ... wozu gibt es denn XE2? :stupid:


2GB ... bei ein 1GB rumliegenden Daten, den sonstigen geladenen DLLs/EXE und dem restlichen belegten Speicher, welches alles wild verteilt im virtuellen Arbeitsspeicher rumliegt, wird es sowieso schwer überhaupt noch ein halbes GB zusammenhängend für den MemoryStream zu finden.

friedemann2009 14. Aug 2011 08:08

AW: Komprimiertes Speichern von Virtual Stringtree / Stream
 
Sonntag, 09.00 Uhr - und schon so viele aktiv! Respekt :)

Zitat:

Zitat von Sir Rufo (Beitrag 1116723)
Die Grenze heißt 32-Bit und kann nur 2GB RAM pro Programm verwalten.

Ok, das wusste ich nicht.. Das dürfte def. eines der Probleme sein..

Zitat:

Zitat von himitsu (Beitrag 1116724)
Welche Delphiversion nutzt du eigentlich?

Nutze noch immer D5... Ich weiß, ein Aufrüsten wäre langsam mal nötig, aber die Professionals sind so teuer, dass ich mir das als wissenschaftlicher Laienprogrammierer (der aus einem anderen Fach kommt) gerade nicht unbedingt leisten kann..

- Und: Ja, ich weiß, dass die VST nur zur Visualisierung dient/dienen soll. Aber als ich die VST kennengelernt habe, war ich so begeistert, dass ich darüber nicht mehr nachgedacht habe. Jetzt müsste ich das komplette Design (~400 Seiten Code) ändern.. Das wäre dann was für eine Version 4,5 o.ä. derzeit bin ich an 2.x) :)

Habe den Stream jetzt mal temporär gespeichert und anschließend komprimiert. Das klappt auch. - Fehlt nur noch eine Progressbar, aber da muss ich mich erst mal in den Foren umsehen, wie ich den Speicher-/Laden-/(De)Komprimier-Fortschritt abgreifen kann.

Danke Euch schon mal!

Gruß, frieder

EDIT: Hm, finde ich gerade nichts zur Fortschrittsanzeige; hat da noch jemand einen Tipp?

himitsu 14. Aug 2011 08:17

AW: Komprimiertes Speichern von Virtual Stringtree / Stream
 
Wegen dem Fortschritt: Man weiß ja nicht, wie groß die Datei mal wird, also ist eine prozenduale Fortschrittsanzeige unmöglich, also beim Erstellen der Datei.
(maximal näherungsweise möglich, indem man die endgültige Größe schätzt)

Du kannst dir aber den FileStream ableiten und in den Schreib-/Lesemethoden deine Fortschrittsanzeige aktualisieren.

Beim Schreiben schreibst du dann z.B. "x Byte verarbeitet" und beim Auslesen "x von y byte verarbeitet" (das nochmalige Speichern hast du dabei über den Lesezyklus mit abgedeckt, da beides ja gleichzeitig geschieht, es sei denn du willst life mit ausgeben, von wieviel auf wieviel aktuell runterkomprimiert wurde).

PS: Eine nette eMail an germany.info@embarcadero.com und man bekommt oftmals noch eine Lizenz für Turbo Delphi (kleineres Delphi 2006).


Alle Zeitangaben in WEZ +1. Es ist jetzt 11:45 Uhr.
Seite 1 von 2  1 2      

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