AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

In Stream schreiben und lesen ?

Ein Thema von madina · begonnen am 24. Jun 2008 · letzter Beitrag vom 26. Jun 2008
Antwort Antwort
madina

Registriert seit: 1. Nov 2005
153 Beiträge
 
#1

In Stream schreiben und lesen ?

  Alt 24. Jun 2008, 07:38
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:
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;
Fehler: beim Lesen wie kann ich die einzelenen Icons (Einträge) aus Stream lesen oder ist das Stream wie Felder ansprechbar ?:

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;
  Mit Zitat antworten Zitat
Benutzerbild von sirius
sirius

Registriert seit: 3. Jan 2007
Ort: Dresden
3.443 Beiträge
 
Delphi 7 Enterprise
 
#2

Re: In Stream schreiben und lesen ?

  Alt 24. Jun 2008, 07:45
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.
Dieser Beitrag ist für Jugendliche unter 18 Jahren nicht geeignet.
  Mit Zitat antworten Zitat
madina

Registriert seit: 1. Nov 2005
153 Beiträge
 
#3

Re: In Stream schreiben und lesen ?

  Alt 25. Jun 2008, 07:23
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
  Mit Zitat antworten Zitat
guidok

Registriert seit: 28. Jun 2007
417 Beiträge
 
#4

Re: In Stream schreiben und lesen ?

  Alt 25. Jun 2008, 13:38
Schau doch mal bei Delphi Treff Tutorial - Streams da erfährst du einiges über den Umgang mit Streams.

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.
  Mit Zitat antworten Zitat
guidok

Registriert seit: 28. Jun 2007
417 Beiträge
 
#5

Re: In Stream schreiben und lesen ?

  Alt 25. Jun 2008, 13:48
Zitat von guidok:
Schau doch mal bei Delphi Treff Tutorial - Streams da erfährst du einiges über den Umgang mit Streams.

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.
Der Vollständigkeit halber, falls die Größe der Icons (oder irgendwelcher Daten) variabel ist, dann sieht dein Stream folgendermaßen aus:

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
  Mit Zitat antworten Zitat
Benutzerbild von sirius
sirius

Registriert seit: 3. Jan 2007
Ort: Dresden
3.443 Beiträge
 
Delphi 7 Enterprise
 
#6

Re: In Stream schreiben und lesen ?

  Alt 25. Jun 2008, 13:54
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;
Dieser Beitrag ist für Jugendliche unter 18 Jahren nicht geeignet.
  Mit Zitat antworten Zitat
25. Jun 2008, 15:42
Dieses Thema wurde von "Matze" von "Programmieren allgemein" nach "Sonstige Fragen zu Delphi" verschoben.
Delphi-Frage
madina

Registriert seit: 1. Nov 2005
153 Beiträge
 
#8

Re: In Stream schreiben und lesen ?

  Alt 26. Jun 2008, 08:36
Hallo,

bitte um Sourcecode:

1. ist dies überhaupt richtig beim Schreiben ???

Delphi-Quellcode:
cdsLand.Insert;
  cdsLand['sLand'] := cbLand.Items[i]; // LandName eintragen
  // LoadBlobFieldFromStream
  TBlobField(cdsLand.FieldByName('blbFahne')).LoadFromStream(Stream); // Icon eintragen (4 Byte).
cdsLand.Post;
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 ??

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
  Mit Zitat antworten Zitat
guidok

Registriert seit: 28. Jun 2007
417 Beiträge
 
#9

Re: In Stream schreiben und lesen ?

  Alt 26. Jun 2008, 08:47
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.
  Mit Zitat antworten Zitat
guidok

Registriert seit: 28. Jun 2007
417 Beiträge
 
#10

Re: In Stream schreiben und lesen ?

  Alt 26. Jun 2008, 08:55
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;
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 20:52 Uhr.
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