![]() |
Effizienter binär-output eines (word)-streams
Ich habe bei einem Algorithmus als output eine liste / einen stream, der werte des typs word (0..65535) enthält.
Jetzt würde ich die liste gerne wieder zu binaer wandeln (chars, bytes) und ausgeben (entweder in einen stream schreiben oder in einem string speichern): Wie kann ich den output möglichst effizient (d.h. kurz) halten? Bisher hatte ich folgende Ansätze: naiv:
Delphi-Quellcode:
einmal noch als words/chars direkt (bisher das kürzeste):
Function Tio_stream.OutputCompressedData(data: Tlist<Pword>)
: Tmemorystream; Var P: Pword; Writer: Tbinarywriter; Begin Result := Tmemorystream.Create; Writer := Tbinarywriter.Create(Result); Try For P In Compressed Do Writer.Write(P^); Finally Writer.Free; End; End; //read Procedure Tio_stream.GetCompressedData(Const Content: Tmemorystream; Out res: Tlist<Pword>); Var Tempdata: Word; Var Tempdataentry: Pword; Var Readindex, Maxread: Word; Datasize: Integer; Begin //assert(assigned(res)); Cleardata(res); Content.Position := 0; Begin Readindex := 0; Datasize := Sizeof(Word); Maxread := Content.Size Div Datasize; While Readindex < Maxread Do Begin Content.Read(Tempdata, Datasize); New(Tempdataentry); Tempdataentry^ := Tempdata; res.Add(Tempdataentry); Inc(Readindex); End; End; End;
Delphi-Quellcode:
Darauf aufbauend hatte ich folgendes versucht (die super klassen tstreamwriter/reader habe ich erst vor kurzem für mich entdeckt)
procedure OutputCompressedData(Compressed: Tlist<Pword>): String;
Var Entry: Pword; Outchar: Pchar; Begin Setlength(Result, Compressed.Count); Outchar := @Result[1]; For Entry In Compressed Do Begin Outchar^ := Char(Entry^); Inc(Outchar); End; // Result := Concat(Result, Char(entry^)); End;
Delphi-Quellcode:
habe aber, wo angegeben, mit dem abstract error (welche klasse überschreibt das denn?) zu tun
Function Tlzwio_stringstream.OutputCompressedData
(Compressed: Tlist<Pword>): String; Var Temp: Tmemorystream; Encoding: Tencoding; Begin Try Assert(Assigned(Compressed)); Encoding := Tencoding.Create; Encoding.Default; // writes values as word to stream Temp := Inherited Outputcompresseddata(Compressed); Temp.Position := 0; With Tstreamreader.Create(Temp, Encoding) Do Begin Result := ReadLine; // abstract error Free; End; Finally Encoding.Free; Temp.Free; End; End; Was haltet ihr davon? #Holzweg? Welche - im obigen sinne - effizienten Alternativen (bitstream klasse, sowas könnte ich an anderer stelle auch gebrauchen?)würdet ihr vorschlagen? danke! |
AW: Effizienter binär-output eines (word)-streams
Lustig, vor ein paar Minuten hatte ich eine ganz ähnliche Frage:
![]() Hier habe ich ein Array von
Delphi-Quellcode:
, und möchte fortan mit einem Array von
Word
Delphi-Quellcode:
weiterarbeiten. Allerdings ohne nochmal neu Speicher anlegen und Daten hin und her schieben zu müssen, die Daten liegen ja bereits vor.
Byte
Bei dir ist es etwas mehr "high-level" und du kontrollierst anscheinend beide Seiten, also den Teil der die Words ausspuckt, und den Teil der die Bytes weiterverarbeiten will, richtig? |
AW: Effizienter binär-output eines (word)-streams
1. Warum keine TList<Word>
Da kann man dann das array der Liste (TList. List[0]) in den Stream schreiben. Laut Wiki kann man TList.Count direkt setzen und dann sollte ein direktes beschreiben von TList.List[0] möglich sein. 2. Was hat ein Word mit strings zu tun? Das array als csv string könnte ich mir vorstellen, aber das meinst du sicher nicht. 3. Wer kümmert sich um die Freigabe von PWord wenn die Liste freigegeben wird? |
AW: Effizienter binär-output eines (word)-streams
@BerndS: Die pwords liegen in der liste (data) und werden nach dem Schreibvorgang in den Stream auch von dort korrekt freigegeben.
Was die words mit strings zu tun haben? ich hatte zunächst die idee, dass bei unicode sizeof(char)=sizeof(word), daher kann ich sie ja direkt in einen string schreiben - ich hatte auch bereits damit experimentiert, einen
Delphi-Quellcode:
zu nutzen und ggf (bei kleinen werten) mit dem nächsten halben word zu füllen. Das macht die sache aber auch nicht unbedingt kürzer.
record
valhi:byte; vallo:byte; end; Ich könnte mir so etwas auch auf Bitebene vorstellen, wie im Originalpost angeregt. So etwas geht bestimmt mit Bitmasken oder so - nur spontan wüsste ich jetzt nicht wie ich das umsetzten sollte. Gibts da fertiges? Macht das überhaupt Sinn? Wie verhält sich das mit der tlist<word>, wenn ich list.list[0] in den stream schreibe? Die einzelnen Einträge sind dann doch immer noch- von der Größe word, egal ob unterhalb der bytegrenze oder nicht? Damit würden die werte 00..FF ja eigentlich immer als 0000..00FF (bzw FF00) abgespeichert. Geht das nicht irgendwie platzsparender? - im moment nutze ich es zb. bei der Ausgabe von dictionary-based Kompressionsalgorithmen (zb. LZW, hier haben die outputs maximal die größe eines words, kleinstenfalls bytegröße)im späteren verlauf würde ich das dann gerne für eine art huffman-baum (-Ausgabe) nutzen wollen. @Der schöne Günther: mir ist auf den ersten blick nicht ganz klar geworden,inwiefern mir der englische Beitrag von dir hilft? Vieleleicht ist es auch schon zu spät - ich müsste mir das mal bei tageslicht ansehen.:oops: |
AW: Effizienter binär-output eines (word)-streams
@Sequitar
Es war gestern wohl schon zu spät für mich um dein Problem zu verstehen. Wenn es so viele Daten sind,das du dir darüber Gedanken machen musst, wäre eine Kompression die beste Lösungen. Ich verwende dafür eine Kompression der LMD Komponenten um Streams in einer Datenbank im Blob zu speichern und wieder zu laden. |
AW: Effizienter binär-output eines (word)-streams
Was du machen kannst ist einen Typen mit mehr als einem Zustand zu verwenden:
Delphi-Quellcode:
Dann hast Du zur gleichen Zeit Zugriff darauf als Word und als Bytes. Das ganze als Array anlegen und nach Möglichkeit blockweise lesen und schreiben. Das spart Zeit beim Zugriff.
type
TDual = packed record case byte of 0 : (a : word); 1 : (b: record hi,lo : byte;end); end; |
AW: Effizienter binär-output eines (word)-streams
Warum das Rad neu erfinden, wenn es doch schon in SysUtils existiert?
Delphi-Quellcode:
{ Type conversion records }
WordRec = packed record case Integer of 0: (Lo, Hi: Byte); 1: (Bytes: array [0..1] of Byte); end; LongRec = packed record case Integer of 0: (Lo, Hi: Word); 1: (Words: array [0..1] of Word); 2: (Bytes: array [0..3] of Byte); end; Int64Rec = packed record case Integer of 0: (Lo, Hi: Cardinal); 1: (Cardinals: array [0..1] of Cardinal); 2: (Words: array [0..3] of Word); 3: (Bytes: array [0..7] of Byte); end; |
AW: Effizienter binär-output eines (word)-streams
Nur das WordRec keinen Zugriff als Word erlaubt, nur als Bytes. Und dann sinnloserweise auch noch auf zwei Arten.
|
AW: Effizienter binär-output eines (word)-streams
Zitat:
Delphi-Quellcode:
var
MyCharArray: array[0..15] of WideChar; begin ... cntHighUnicode := 0; for I := Low(MyCharArray) to High(MyCharArray) do if WordRec(MyCharArray[0]).Hi <> 0 then Inc(cntHighUnicode); ... end; Der zugegeben redundante Zugriff auf die Einzelbytes ist wohl eher der Konsistenz mit den anderen record Typen geschuldet. |
AW: Effizienter binär-output eines (word)-streams
Hm danke für eure Ideen. Allerdings bin ich mir beim durchlesen nicht mehr sicher, ob ich mein problem richig dargestellt habe.(u.a @BerndS)
Also sagen wir ich habe als output die list<word>, welche ich in den output stream schreiben möchte. Natürlich geht das erst mal intuitiv ungefähr so: Nur vom prinzip her - ohne auf Schönheit zu achten.
Delphi-Quellcode:
dann habe ich am ende einen output stream der groesse list.count*wordsize.
//..
from i:=list.lo to list.hi do begin var x:word:=list[i] stream.write{oder streamwriter().write}(x,wordsize); end; Meine Frage wäre: Geht das kürzer, z.b wenn ich ungefähr weiss, dass die meisten werte werte >high(byte) sein werden? Ich meine, vielleicht geht's ja auch gar nicht. Gut, was mir jetzt noch einfällt - den könnte ich - zum Beispiel - noch mal durch eine Lauflängen-Kompression schicken (müsste ich mal probieren, ob das was bringt, bei vielen wiederholungen vielleicht), oder durch einen Huffman-Tree oder so ähnlich, damit ich am ende eine art bit-stream habe. Bevor ich das anfange, wäre ich allerdings an möglichkeiten interessiert, die es mir erlauben, eine Ausgabefolge von word-werten reversibel(!) in eine effizientere Form zu bringen |
Alle Zeitangaben in WEZ +1. Es ist jetzt 12:26 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