![]() |
Ordentliche Komprimierungsunit
Hallo Wissende,
wollte mal fragen, ob jemand von euch eine ordentlche Komprimierungsunit hat, welche man sowohl in kommerziellen als auch in OS Projekten einsetzen darf. Die ZLib funktioniert ja halbwegs, schafft schon mal 2°/oo an Komprimierung oder vergrössert gleich um 100% beim komprimieren ;-) . Wenn man dann die Datei mit einem HexEditor ansieht, sieht sie unverändert aus. Also scheint sie wohl nicht so das richtige zu sein. Aber vielleicht kennt ja einer von euch, da was Sinnvolles :-) Schöne Grüße Greeny |
Re: Ordentliche Komprimierungsunit
Zitat:
|
Re: Ordentliche Komprimierungsunit
*push*
weiss keiner, wie man Streams ordentlich komprimieren kann? Wobei die Unit für Closed und OS geeignet sein sollte? :stupid: :stupid: :stupid: |
Re: Ordentliche Komprimierungsunit
ZLib.
Meinst du nicht auch, dass wenn sie der Maßen schlecht funktionieren würde, dass sich da nicht schon andere gemeldet hätten? Du kannst jetzt entweder weiter nach einer Alternative suchen oder du zeigst uns mal deinen Code und wir suchen deinen Fehler. |
Re: Ordentliche Komprimierungsunit
Liste der Anhänge anzeigen (Anzahl: 2)
Hallo Luckie,
dann mal viel Spass beim Suchen :-) . Habe gerade ein kleines Testprojekt zusammengezimmert, sollte aber für einen Einblick genügen. Edit: Update der Compremierungsroutine (Position := 0 vergessen)
Delphi-Quellcode:
Grüße
procedure TForm2.Compress;
var zc: TZCompressionStream; ms1: TMemoryStream; buff: array [0..2048] of byte; len: integer; begin ms1 := TMemoryStream.Create; try zc := TZCompressionStream.Create(ms1, zcMax); try ms.Position := 0; repeat len := ms.Read(buff, 2048); zc.Write(buff, len); until len <> 2048; lRateOfCompression.Caption := Format('%.3f', [zc.CompressionRate]); ms.Position := 0; ms.CopyFrom(ms1, ms1.Size); finally zc.free; end; finally ms1.Free; end; end; das GreenHorn |
Re: Ordentliche Komprimierungsunit
Du musst den Zielstream (glaube ich) vor'm kopieren leeren, sonst behält der die alte Länge und wird höchstens länger.
|
Re: Ordentliche Komprimierungsunit
Das ist so, ja. Leeren oder die Größe danach auf die neue Größe setzen. ;-)
|
Re: Ordentliche Komprimierungsunit
Hallo Dax, Jänicke,
mhhh, ist nicht wirklich hilfreich. Wie ihr mit einem Blick auf den Code erkennen könnt, wird der Ausgabestream neu (also leer) erzeugt. Er wird ja auch prima gefüllt. Nur, ist dann der Inhalt reichlich unkomprimiert... Dies war ja auch meine Kritik dran, daher die Frage nach einer anderen, welche es besser kann. Übrigens, ein kleines Beispielprojekt ist angehangen, nur die Methode ist gegen die aktuelle hier aus dem obigen Post zu tauschen. Greeny |
Re: Ordentliche Komprimierungsunit
Zitat:
Ansonsten liest du aus einem anderem Stream (ms) und schreibst diesen in cz/ms1. Anschließend kopierst du den komprimierten Stream an den Anfang des Streams aus dem du die ganze Zeit gelesen hast. Ist dein unkomprimierter Stream also z.B. 5 MB groß und die komprimierten Daten sind 1 MB groß, so schreibst du diese 1 MB an den anfang des Ursprüngsstreams. Die restlichen 4 MB des Ursprungsstreams bleiben allerdings erhalten so das deine Datei weiterhin 5 MB groß ist. Welchen Sinn macht das? Zudem verstehe ich deine Vorgehensweise mit der Schleife nicht. Warum verwendest du an dieser Stelle nicht bereits die CopyFrom-Methode? |
Re: Ordentliche Komprimierungsunit
Hi Greeny,
Für dich dürfte es keine geeignete Kompressions-Unit geben. Du kannst nämlich mit egal welcher Klasse nicht richtig umgehen. :thumb: Bei mir funktioniert ZLib ganz prächtig, aber ich weiss auch, wie man die Library verwenden muss. Der Hauptfehler befindet sich übrigens in 99% der Fälle ca. 80cm vom Bildschirm entfernt und zeigt mit dem Finger auf andere. :mrgreen: Hier eine dezent korrigierte Version, sowie eine Alternative, die etwas kompakter ist, da sie den zu komprimierenden Stream einfach per CopyFrom direkt in ZLib reinbläst, anstatt sie in 2k-Happen zu komprimieren (Meine Unit kennt übrigens kein TZCompressionStream, vielleicht liegt es auch daran):
Delphi-Quellcode:
Bevor Du dich über meine Sticheleien echauffierst, bedenke, das Du dich sehr weit aus dem Fenster gelehnt hast und offenbar über eine gehörige Portion Selbstbewustsein verfügst, denn sonst würdest Du nicht allen Ernstes als 'GreenHorn' eine dermaßen erprobte Unit wie ZLib in Frage stellen. Soviel Chuzpe muss man erstmal haben :lol:
procedure TForm2.Compress;
var zc: TCompressionStream; ms1: TMemoryStream; buff: array[0..2048] of byte; len: integer; begin ms1 := TMemoryStream.Create; ms.position := 0; // 1.Fehler, ms war am Ende und u.g. 'read' lieferte 0 bytes. try zc := TCompressionStream.Create(clMax, ms1); try repeat len := ms.Read(buff, 2048); zc.Write(buff, len); until len <> 2048; lRateOfCompression.Caption := Format('%.3f', [zc.CompressionRate]); finally zc.free; // 2.Fehler: Der ZCompressionStream hat noch Einiges im Puffer end; ms.clear; // 3.Fehler: Alten Stream löschen ms.CopyFrom(ms1, 0); // 4.Fehler: ms1 komplett von Anfang an kopieren finally ms1.Free; end; end; procedure TForm2.Compress1; var zc: TCompressionStream; ms1: TMemoryStream; begin ms1 := TMemoryStream.Create; try zc := TCompressionStream.Create(clMax, ms1); try zc.CopyFrom(ms, 0); finally zc.free; end; lRateOfCompression.Caption := Format('%.3f', [zc.CompressionRate]); ms.clear; ms.CopyFrom(ms1, 0); finally ms1.free; end; end; :cheers: |
Re: Ordentliche Komprimierungsunit
Zitat:
|
Re: Ordentliche Komprimierungsunit
Hallo alzaimar,
dank Dir. Ich bin ja auch nur ein GreenHorn. Hab aber noch ein paar fragen dazu. Mein Stream (TStream) kennt kein .Clear wie kann man das dennoch wieder säubern? Andere Frage, beim Stream schreibst Du
Delphi-Quellcode:
Dies ist definiert als:
zc.CopyFrom(ms, 0)
Delphi-Quellcode:
Weshalb Funktioniert dann
function TStream.CopyFrom(Source: TStream; Count: Int64): Int64;
... begin if Count = 0 then begin Source.Position := 0; Count := Source.Size; end;
Delphi-Quellcode:
nicht?
zc.CopyFrom(ms, ms.size)
Dank Euch, das GreenHorn |
Re: Ordentliche Komprimierungsunit
Wenn clear nicht vorhanden ist kann man auch einfach mit dem Property-Size die Größe auf 0 setzen.
Oder was in den meisten Fällen performanter ist - die Größe gleich auf den richtigen Wert setzen. In diesem Fall also:
Delphi-Quellcode:
procedure CompressStream(ms: TStream);
var zc: TCompressionStream; ms1: TMemoryStream; begin ms1 := TMemoryStream.Create; try zc := TCompressionStream.Create(clMax, ms1); try zc.CopyFrom(ms, 0); finally zc.free; end; lRateOfCompression.Caption := Format('%.3f', [zc.CompressionRate]); ms.size := ms1.size; ms.position := 0; ms1.postion := 0; ms.CopyFrom(ms1, ms1.size); finally ms1.free; end; end; Zitat:
|
Re: Ordentliche Komprimierungsunit
Hallo Wissende,
kann man diesen Code noch optimieren? Geht darum, dass der Stream aStream komprimiert wird und der komprimierte anschliessend wieder im aStream zurückgegeben wird.
Delphi-Quellcode:
@SirThornberry: beim aStream.copyfrom(ms, ms.size), sass wohl das Problem vor dem Bildschirm. Danke.
procedure CompressStream(aStream: TStream);
var zc: TZCompressionStream; ms: TMemoryStream; begin ms := TMemoryStream.Create; try zc := TZCompressionStream.Create(ms, zcMax); try zc.CopyFrom(aStream, 0); finally zc.Free; end; aStream.Size := 0; aStream.copyFrom(ms, 0); finally ms.Free; end; Greeny |
Re: Ordentliche Komprimierungsunit
Vielleicht geht es so schneller?
Delphi-Quellcode:
Grüße
procedure CompressStream(aStream: TStream);
var zc: TZCompressionStream; ms: TStream; begin ms := (ms as TMemoryStream).Create; zc := TZCompressionStream.Create(ms, zcMax); try zc.CopyFrom(aStream, 0); finally zc.Free; end; aStream.Free aStream:=ms; end; Klaus |
Re: Ordentliche Komprimierungsunit
Als Alternative zur ZLIB würde ich gerne noch
![]() |
Re: Ordentliche Komprimierungsunit
Zitat:
1. ms := (ms as TMemoryStream).Create; sollte ne Exception werfen, wenn dann so: ms := TMemoryStream.Create; 2. astream müsste als var Parameter deklariert werden. So wird der übergebene Stream freiegegeben, und der lokale nicht. Zur Logik: Ich darf nen beliebigen Stream reinpacken, und der wird hinterrücks freigeben und durch einen Memorystream ersetzt. Als hätte der Autor überlegt "Hmmm ... wie könnte ich das programmieren, damit der Zweck zwar erfüllt wird, aber die Funktion trotzdem möglichst unerwartet reagiert?" |
Re: Ordentliche Komprimierungsunit
Zitat:
Adresse des intern erzeugten Streams zugewiesen bekommt. So könnte das unkopieren entfallen. Im Punkt 1 gebe ich Dir recht. Objekte die als Paramter einer Routine übergeben werden müßen nicht als var gekennzeichnet werden damit Änderungen auch ausserhalb der Routine wahrgenommen werden. Grüße Klaus |
Re: Ordentliche Komprimierungsunit
Wenn man ein Objekt an eine Funktion "normal" übergibt, geschieht dies mit call-by-value. Es wird also der Zeiger, der auf das Objekt zeigt kopiert und der Funktion gegeben.
Alles was im Objekt ist, wird natürlich nicht kopiert und Änderungen wirken sich auf den Aufrufer aus. Der Zeiger selbst wird aber immernoch kopiert - d.h. es gibt 2 Zeiger (einen beim Aufrufer und einen in der Funktion). Wenn du also auf deiesen Zeiger ein aValue.Free() ausführst wird das Orginal-Objekt zerstört. Jetzt sagst du: aValue := ms; damit wird der lokalen Kopie des Zeigers die Adresse des internen Streams zugewiesen. Der äußere Zeiger bleibt unverändert. Beim Verlassen der Funktion wird der Zeiger dann auch weggeworfen. Wer auch immer diese Funktion aufruft, hat danach einen ungültigen Zeiger und ein Speicherleck :stupid: Der var-Parameter würde dafür sogen, dass der Zeiger nicht kopiert wird, sondern sozusagen ein Zeiger auf den Zeiger übergeben wird. Dann kannst du auch den Orginal-Zeiger ändern. Gut ist das alles abder trotzdem nicht (weshalb sich diese Frage beim normalen Programmieren auch nicht stellt :P ). Stell dir vor, du öffnest eine Datei und willst die komprimieren. Du übergibt also nen Filestream und bekommt ... einen Memorystream zurück, in dem die komprimierte Datei steht. Der Filestream wurde freigegeben. Tolle Logik :mrgreen: |
Re: Ordentliche Komprimierungsunit
Halo Mirage,
danke für den Tipp, aber das ganze sollte schon mit Bordmitteln funktionieren, oder zumindest für OS und kommerzielle Programme (kostenlos) einsetzbar sein. Und da gibt es dann halt nicht mehr viel :-( Gut, die ZLib, komprimiert jetzt mal, aber so ordentlich auch nicht. Sie schafft da Grad mal 1,44%, aber immerhin... BTW: @alzaimer: der TZCompress ist der Name aus der unit zLib unter D2.9 unter D2.6 ist das ganze noch ohne Z . Dafür kann er keine Memorystreams. Kennst Du hier vielleicht einen Trick, um ihm Memorystreams beizubringen (in D2.6)? Grüße Greeny |
Re: Ordentliche Komprimierungsunit
Da bekomm ich echt Sodbrennen...
Zitat:
Zitat:
|
Re: Ordentliche Komprimierungsunit
Zu Testzwecken, hatte ich eine .CHM komprimiert, unkomprimiert 418KB komprimiert mit zLIB (Maximal) 412KB. Also, kleiner ist sie schon geworden, hätte aber da schon ein paar %'te mehr erwartet, so auf ca. 360KB, oder so...
Zu der Aussage komme ich, weil ich das akutelle Projekt mal mit D2.6 geöffnet hab, dachte mir, nimmst das Z weg und das läuft... und da bringt er mir den Fehler, daß er mit TMemory Streams nichts anfangen kann. Unter D2.9 ist dies alles kein Problem. Schöne Grüße Greeny |
Re: Ordentliche Komprimierungsunit
Zitat:
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 16:10 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