![]() |
Progress beim komprimieren mit CompressBuf anzeigen
Hallo,
wie kann ich es realisieren, dass: 1. Das Programm beim komprimieren vongrößeren Dateien nicht einfriert. 2. Eine Fortschrittanzeige einbauen Ich benutze diesen Code:
Delphi-Quellcode:
Florian
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; procedure DecompressStream(inpStream, outStream: TStream); var InpBuf, OutBuf: Pointer; OutBytes, sz: Integer; begin InpBuf := nil; OutBuf := nil; sz := inpStream.Size - inpStream.Position; if sz > 0 then try GetMem(InpBuf, sz); inpStream.Read(InpBuf^, sz); DecompressBuf(InpBuf, sz, 0, OutBuf, OutBytes); outStream.Write(OutBuf^, OutBytes); finally if InpBuf <> nil then FreeMem(InpBuf); if OutBuf <> nil then FreeMem(OutBuf); end; outStream.Position := 0; end; |
Re: Progress beim komprimieren mit CompressBuf anzeigen
für ersteres wirst du es in einen thread auslagern müssen. für zweiteres wirst du um eine schätzung der zeit nicht rumkommen....
EDIT: es sei denn, du zerteilst deinen buffer in hundert gleich große teile und dekomprismierst die einzeln. dann wäre das recht einfach zu lösen. |
Re: Progress beim komprimieren mit CompressBuf anzeigen
Ja, daran hab ich auch schon gedacht!
Nur leider kenne ich mich mit Threads nicht so gut aus. (meine 1. versuche sind alle gescheitert) Und das Aufteilen des Buffers traue ich mir auch nicht zu. Und wie kann man das machen, das das Programm nicht weitermacht ohne einzugfrieren, bis der Thread fertig ist? Kannst du vielleicht Quelltext posten? :-D Florian |
Re: Progress beim komprimieren mit CompressBuf anzeigen
da ham wir nen experten namens luckie, der hat da n tut dazu geschrieben:
![]() und n working example: ![]() du müsstest allerdings noch mit pointern arbeiten, wie das geht, weiss ich nicht. habs zumindest nach (einmaliger) lektüre des tuts nicht gescheckt. :gruebel: |
Re: Progress beim komprimieren mit CompressBuf anzeigen
Danke, ich werd's mir mal ansehen.
Aber wie mache ich das mit dem Aufteilen des Bufs? :gruebel: Florian |
Re: Progress beim komprimieren mit CompressBuf anzeigen
na deine compressbuf-funktion fragt dich doch bei den inpbytes, wie viel sie komprimieren soll, oder? (outbuf und outbytes sind dann ja wohl var-parameter, oder?)
ich hab jetzt n bisschen rumprobiert, aber ohne die compressbuf-funktion komm ich nicht weiter. |
Re: Progress beim komprimieren mit CompressBuf anzeigen
die compressbuf funktion ist bei d7 in der unit zlib enthalten!
Mann müsste praktisch den buf von byte 1 - 100, dann von 100 - 200, usw komprmieren und dann wieder zusammensetzen. Florian |
Re: Progress beim komprimieren mit CompressBuf anzeigen
Hallo Florian,
das Komprimieren mit statistischer Kodierung (ZIP) entfaltet seine Vorteile erst bei größeren Blöcken. Außerdem ist ein Progressbar bei kleinen Wartezeiten eher nervig. Sowas macht man erst, wenn richtige Wartezeiten enstehen - deutlich jenseits der 2-Sekunden Grenze. Dann solltest du auch den CompressionStream und nicht CompressBuf() verwenden. Der Stream kennt das Ereignis OnProgress, mit dem du deinen ProgressBar steuern kannst. Grüße vom marabu |
Re: Progress beim komprimieren mit CompressBuf anzeigen
Kannst du mir ein Beispiel geben, wie ich den Oberen Code einfach umschreiben kann? (Parameter, etc sollen gleich bleiben, da der Code in einem unfassenden Projekt verankert ist)
Ich hab bis jetzt noch nie mit CompressionStream gearbeitet ... Florian |
Re: Progress beim komprimieren mit CompressBuf anzeigen
Auf die Schnelle - kommst du damit zurecht?
Delphi-Quellcode:
marabu
procedure TForm1.OnProgress(Sender: TObject);
begin with Sender as TCompressionStream do begin ProgressBar.Position := Position; Application.ProcessMessages; end; end; procedure CompressStream(inStream, outStream: TStream); var cs: TCompressionStream; begin Form1.ProgressBar.Max := inStream.Size; cs := TCompressionStream.Create(clDefault, outStream); cs.CopyFrom(inStream, inStream.Size); cs.OnProgress := Form1.OnProgress; cs.Free; end; |
Re: Progress beim komprimieren mit CompressBuf anzeigen
Ja, vielen Dank!
Zum dekomprimieren muss ich dann TDecompressionStream verwenden, oder? Florian |
Re: Progress beim komprimieren mit CompressBuf anzeigen
Falls du noch eine Antwort erwartest - Ja.
marabu |
Re: Progress beim komprimieren mit CompressBuf anzeigen
Hallo,
ich habe mehrere Probleme mit der Funktion mit Progress. Das komprmieren an sich funktioniert, nur wird das OnProgress Ereigniss nie abgearbeitet! :cry: :wall: :gruebel: Beim Dekomprimieren (aus dem Code oben selbst zusammengefriemelt) bekomme ich immer, wenn ich auf eine eigenschaft des dekompressionstreams zugreifen will den Fehler: Ungültige Stream Operation! :wall: Meine Funktion
Delphi-Quellcode:
Florian
procedure deCompressStream(inStream, outStream: TStream);
var cs: deTCompressionStream; begin Form1.ProgressBar2.Max := inStream.Size; cs := TdeCompressionStream.Create(inStream); outstream.CopyFrom(cs, cs.Size); cs.OnProgress := Form1.OnDecompressProgress; cs.Free; end; |
Re: Progress beim komprimieren mit CompressBuf anzeigen
Abgesehen von den Tippfehlern - der Code für das OnProgress-Ereignis muss vor dem CopyFrom angegeben werden, sonst kommst du nach der Feier.
marabu |
Re: Progress beim komprimieren mit CompressBuf anzeigen
Oder porbier mal den TStreamProgressAdaper:
![]() |
Re: Progress beim komprimieren mit CompressBuf anzeigen
Stimmt!
Das OnProgress Ereigniss wird jetzt aufgerufen und die Datei komprimiert. :-D Aber entweder ist meine ZLib Unit fehlerhaft, oder es gibt irgend einen Trick, wie ich den TDecompressionStream verwenden muss. Auch wenn ich vorher OnDecompressProgress zuweise kommt spätestens bei
Delphi-Quellcode:
der Fehler: "Ungültige Stream Operation". :?:
OutStream.CopyFrom(cs, cs.Size)
Ich habe ein wenig runprobiert und der Fehler kommt z.B. auch wenn ich nach
Delphi-Quellcode:
auf z.b.
cs := TDecompressionStream.Create(instream)
Delphi-Quellcode:
zugreife! :wall:
cs.Size
Fals ihr denkt, dass es an der ZLib liegt, könnte einer die Hochladen? Weil z.b. der ![]() Florian |
Re: Progress beim komprimieren mit CompressBuf anzeigen
Hai Florian,
wenn Du noch keine Lösung gefunden hast versuche es mal so:
Delphi-Quellcode:
procedure DeCompressStream(inStream, outStream: TStream);
var cs: TDeCompressionStream; Buf: array[0..4095] of byte; Count: integer; begin inStream.Position := 0; cs := TDeCompressionStream.Create(inStream); cs.OnProgress := nil; cs.Position := 0; repeat Count := cs.Read(Buf[0], SizeOf(Buf)); if Count > 0 then begin outStream.Write(Buf[0], Count) end; until (Count = 0); cs.Free; end; |
Alle Zeitangaben in WEZ +1. Es ist jetzt 14:01 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz