![]() |
In Stream schreiben und lesen ?
Hallo an alle,
ich habe ein TClientDataSet mit den Feldern: 1.AutoInc (Integer), 2.LandName (String), 3. TIcon (Blob): mit fester Größe und will den 3.TIcon mit Icons (Typ Blob) füllen. Schreiben eines Icons in das Feld TIcon wie folgt kein Problem:
Delphi-Quellcode:
Fehler: beim Lesen wie kann ich die einzelenen Icons (Einträge) aus Stream lesen oder ist das Stream wie Felder ansprechbar ?:
begin
Stream:= nil; try // CreateStream Stream:= TMemoryStream.Create; frmMain.CDS_Laden(cdsLand, '\Land.dat'); for i:=0 to 240 do begin frmMain.ilFlaggen.GetIcon(i, icBild); // SaveImageToStream icBild.SaveToStream(Stream); Stream.Position:= i; // ist richtig ???? cdsLand.Insert; cdsLand['sLand'] := cbLand.Items[i]; // LandName eintragen // LoadBlobFieldFromStream TBlobField(cdsLand.FieldByName('blbFahne')).LoadFromStream(Stream); // Icon eintragen cdsLand.Post; end except Stream.Free; raise; end; Stream.Free; end;
Delphi-Quellcode:
begin
Stream:= nil; try // CreateStream Stream:= TMemoryStream.Create; // DatenLesen TBlobField(cdsLand.FieldByName('blbFahne')).SaveToStream(Stream); Stream.Position:= 10; // ist richtig ??? // Stream.Seek(0, soFromCurrent); icBild.LoadFromStream(Stream); Image1.Picture.Assign(icBild); except Stream.Free; raise; end; Stream.Free; end; |
Re: In Stream schreiben und lesen ?
Wenn du mehrere Icons im Stream speichern willst, kannst du nicht die Position jedesmal zurücksetzen. Dann überschreibst du doch dein letztes Icon.
Du müsstest die entweder die Größe des Icons mit im Stream speichern oder du hast eine konstante, feste Größe. |
Re: In Stream schreiben und lesen ?
Hallo,
mir ist leider immer noch nicht klar wie ich die Icons als Blob in die TClientDataSet schreiben und wie ich dies lesen soll zumindest bei den von mir angegebenen Source klappt dies nicht. Frage ist wie ich die Größe des gleich größigen Icons beim lesen bestimme und wie ich den Offset erhöhe bitte um ein Beispiel. mfg |
Re: In Stream schreiben und lesen ?
Schau doch mal bei
![]() Grundsätzlich ist es bei Streams so, dass du KEIN Datenformat mit abspeicherst, d.h. es wird einfach ein Byte nach dem anderen abgelegt. Was du dann draus machst ist dir überlassen. Ein Beispiel: Du willst einen String in einen Stream schreiben, dann schreibst du zunächst die Größe des Strings in den Stream und anschließend den String selbst. Beim Lesen liest du zuerst die am Anfang des Streams stehende Länge ein und anschließend weißt du wieviele Byte an Daten noch für den String folgen und gelesen werden müssen. In deinem Fall (wenn ich das richtig verstanden habe) schreibst du als erstes die Anzahl Icons in den Stream und danach ein Icon nach dem anderen. Das geht so nur, wenn die Größe der Icons fest steht und konstant ist. Zum Lesen, als erstes die Anzahl der Icons aus dem Stream lesen und dann blockweise (Blockgröße = Icongröße) ein Icon nach dem anderen. |
Re: In Stream schreiben und lesen ?
Zitat:
Anzahl der Icons im Stream Größe des ersten Icons Daten des ersten Icons Größe des zweiten Icons Daten des zweiten Icons ... Größe des letzten Icons Daten des letzten Icons |
Re: In Stream schreiben und lesen ?
Mein Vorschlag (ungetestet) wäre wie folgt:
Du baust dir deinen Stream aus mehreren einzelnen Streams (welche den einzelnen Icons entsprechen) zusammen und speicherst vorher immer noch die Länge des folgenden Icons.
Delphi-Quellcode:
var c:cardinal;
tempStream:TMemorytsream; begin Stream:= TMemoryStream.Create; tempStream:=TMemorystream.Create; try frmMain.CDS_Laden(cdsLand, '\Land.dat'); for i:=0 to 240 do begin frmMain.ilFlaggen.GetIcon(i, icBild); // SaveImageToStream tempstream.clear; icBild.SaveToStream(tempStream); c:=tempstream.size; stream.write(c,4); //Größe des IconStreams speichern tempstream.seek(0,sofrombeginnig); stream.copyfrom(tempstream,c); //IconStream kopieren / anhängen cdsLand.Insert; cdsLand['sLand'] := cbLand.Items[i]; // LandName eintragen // LoadBlobFieldFromStream TBlobField(cdsLand.FieldByName('blbFahne')).LoadFromStream(Stream); // Icon eintragen cdsLand.Post; end; finally Stream.free; tempstream.free; end; end; begin Stream:= TMemoryStream.Create; tempStream:=TMemorystream.Create; try //warum hier keine Schleife? // DatenLesen TBlobField(cdsLand.FieldByName('blbFahne')).SaveToStream(Stream); Stream.seek(0,sofrombeginnig); Stream.read(c,4); //Länge des ersten/nächsten Icons lesen tempstream.clear; tempstream.copyfrom(stream,c); //Icon rauskopieren icBild.LoadFromStream(tempStream); Image1.Picture.Assign(icBild); finally Stream.Free; tempstream.free; end; end; |
DP-Maintenance
Dieses Thema wurde von "Matze" von "Programmieren allgemein" nach "Sonstige Fragen zu Delphi" verschoben.
Delphi-Frage |
Re: In Stream schreiben und lesen ?
Hallo,
bitte um Sourcecode: 1. ist dies überhaupt richtig beim Schreiben ???
Delphi-Quellcode:
ich habe den Eindruck, daß bei jedem Schleifendurchlauf schreibe ich den kompleten Stream (von 0 bis zum aktuellen Schleifenanzahl) in jedem TClientDataSet Datensatz und dadurch bläht sich TClientDataSet auf ??
cdsLand.Insert;
cdsLand['sLand'] := cbLand.Items[i]; // LandName eintragen // LoadBlobFieldFromStream TBlobField(cdsLand.FieldByName('blbFahne')).LoadFromStream(Stream); // Icon eintragen (4 Byte). cdsLand.Post; 2. ist es möglich durch jeden Schleifendurchgang den Stream um die Icongröße zu vergrößern und zwar wie ? und nicht am Anfang, wo ich vielleicht nicht weiß wieviele Icons ich da hineinpacke. 3. wie sieht die Schleife mit dem Lesen der einzelnen Icons aus dem TClientDataSet ? mfg |
Re: In Stream schreiben und lesen ?
Ohne jetzt genauer auf deinen Code einzugehen:
1. Mit LoadFromStream lädst du den gesamten Stream. Ich hatte das selbe Problem einmal, als ich mehrere Bilder in einen Stream schreiben wollte. Ich habe mir dazu einen temporären MemoryStream erzeugt, in dem ich das Bitmap mit LoadFromStream, bzw. WriteToStream gepackt habe (genau ein Bitmap). Zusätzlich hatte ich einen FileStream in den, Bitmap für Bitmap, der temporäre Stream geschrieben wurde (natürlich mit den entsprechenden Größenangaben des jeweiligen Bitmaps, damit auch wieder zurück gelesen werden kann). 2. Natürlich ist das möglich, sobald du verstanden hast, wie der Stream funktioniert, dann wirst du das auch umsetzen können, in aller Kürze: Die Anzahl deiner Icons im Stream steht in den ersten vier Byte des Stream (LongInt), danach folgt ein Icon. Nun musst du dir zunächst merken, wo du aktuell im Stream stehst. Du setzt die Streamposition auf den Anfang (auf die Anzahl der Icons) und schreibst die neue Anzahl in den Stream. Danach setzt du die Streamposition wieder auf den gemerkten Wert (auf das Ende des zuletzt gespeicherten Icons). Da deine Icons alle gleich groß sind bestünde auch die Möglichkeit die Position aus der Anzahl und Größe der Icons zu errechnen, ganz wie du willst. 3. Kann ich jetzt nichts dazu sagen, weil ich mich nicht näher mit beschäftigt habe. |
Re: In Stream schreiben und lesen ?
Ich hab den Code grade wiedergefunden. In den Stream werden in diesem Fall mehrere Datensätze vom Typ TCard geschrieben. Der besteht unter anderem aus einem Bitmap und mehreren Strings.
Delphi-Quellcode:
type TCard = record Bitmap: TBitmap; //Kartenbild Name: String; //Kartenname Description: String;//Kartenbeschreibung Kind: String; //Kartentyp Action: String; //Auszuführende Aktionen end; procedure TCardset.ReadFromFile(Filename: string); var lFs: TFileStream; lMs: TMemoryStream; lLen: Longint; lI: Integer; begin Free; lFs:=TFileStream.Create(Filename,fmOpenRead); lMs:=TMemoryStream.Create; try //Länge des Cardset lFS.Read(lLen,SizeOf(lLen)); SetLength(Cards,lLen); //Die Daten des Cardset speichern for lI := 0 to Length(Cards) - 1 do begin //Bitmap lMs.Clear; lFs.Read(lLen,SizeOf(lLen)); lMs.CopyFrom(lFs,lLen); Cards[lI].Bitmap:=TBitmap.Create; lMs.Position:=0; Cards[lI].Bitmap.LoadFromStream(lMs); //Strings lFs.Read(lLen,SizeOf(lLen)); SetLength(Cards[lI].Name,lLen); lFs.Read(PChar(Cards[lI].Name)^,lLen); lFs.Read(lLen,SizeOf(lLen)); SetLength(Cards[lI].Kind,lLen); lFs.Read(PChar(Cards[lI].Kind)^,lLen); lFs.Read(lLen,SizeOf(lLen)); SetLength(Cards[lI].Description,lLen); lFs.Read(PChar(Cards[lI].Description)^,lLen); lFs.Read(lLen,SizeOf(lLen)); SetLength(Cards[lI].Action,lLen); lFs.Read(PChar(Cards[lI].Action)^,lLen); end; finally lFS.Free; lMs.Free; end; end; procedure TCardset.SaveToFile(Filename: string); var lFs: TFileStream; lMs: TMemoryStream; lLen: Longint; lI: Integer; begin lFs:=TFileStream.Create(Filename,fmCreate); lMs:=TMemoryStream.Create; try //Länge des Cardset lLen:=Length(Cards); lFs.Write(lLen,SizeOf(lLen)); //Die Daten des Cardset speichern for lI := 0 to Length(Cards) - 1 do begin //Bitmap lMs.Clear; Cards[lI].Bitmap.SaveToStream(lMs); lMs.Position:=0; lLen:=lMs.Size; lFs.Write(lLen,SizeOf(lLen)); lFs.CopyFrom(lMs,lLen); //Strings lLen:=Length(Cards[lI].Name); lFs.Write(lLen,SizeOf(lLen)); lFs.Write(PChar(Cards[lI].Name)^,lLen); lLen:=Length(Cards[lI].Kind); lFs.Write(lLen,SizeOf(lLen)); lFs.Write(PChar(Cards[lI].Kind)^,lLen); lLen:=Length(Cards[lI].Description); lFs.Write(lLen,SizeOf(lLen)); lFs.Write(PChar(Cards[lI].Description)^,lLen); lLen:=Length(Cards[lI].Action); lFs.Write(lLen,SizeOf(lLen)); lFs.Write(PChar(Cards[lI].Action)^,lLen); end; finally lFs.Free; lMs.Free; end; end; |
Alle Zeitangaben in WEZ +1. Es ist jetzt 01:16 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