Autor |
Beitrag |
Martok
Beiträge: 3661
Erhaltene Danke: 604
Win 8.1, Win 10 x64
Pascal: Lazarus Snapshot, Delphi 7,2007; PHP, JS: WebStorm
|
Verfasst: So 13.01.13 20:23
catweasel hat folgendes geschrieben : | Als ich auf der Embacaero Website mir ein paar Sachen dazu durchgelesen habe: docwiki.embarcadero....stem.Classes.TWriter bin ich etwas verwirrt. Dort steht das man TReader/TWriter nicht direkt erzeugen soll weil das sowieso schon Bestandteil der TSTream Klasse ist. |
Und bei den passenden TStream-Funktionen steht dann, dass man die auch nicht nutzen soll. Halte ich für Blödsinn; das steht aber allgemein bei vielem dran, was auch nur entfernt mit Component-Streaming zu tun hat.
Ein Hinweis noch: TReader/Writer verwenden zusätzlich zu den Daten jeweils noch eine 1-Byte-Kennung, die den Typ der Daten angibt. Damit hast du gleich eine Art Konsistenzprüfung, brauchst aber auch mehr Platz: WriteInteger() schreibt eben nicht 4 Byte, sondern 5.
catweasel hat folgendes geschrieben : | Und was ist die Obergrenze für die Buffergröße?. Hab dazu auch nichts gefunden. |
Bis der RAM voll ist
Sinnvollerweise sollte man das an 4K-Schritten ausrichten, aber kommt natürlich auch drauf an wie viel du schreiben willst. Wenn deine ganze Datei nachher 10MByte groß wird lohnt sich ein großer Buffer (Windows nimmt gern 64k) eher als wenn die Datei sowieso nur 100 Byte wird.
_________________ "The phoenix's price isn't inevitable. It's not part of some deep balance built into the universe. It's just the parts of the game where you haven't figured out yet how to cheat."
|
|
catweasel
Beiträge: 487
Erhaltene Danke: 1
Win 7 64bit
Delphi 7 Second Sedition V7.2
|
Verfasst: Sa 19.01.13 00:31
Martok hat folgendes geschrieben : | catweasel hat folgendes geschrieben : | Als ich auf der Embacaero Website mir ein paar Sachen dazu durchgelesen habe: docwiki.embarcadero....stem.Classes.TWriter bin ich etwas verwirrt. Dort steht das man TReader/TWriter nicht direkt erzeugen soll weil das sowieso schon Bestandteil der TSTream Klasse ist. | Und bei den passenden TStream-Funktionen steht dann, dass man die auch nicht nutzen soll. Halte ich für Blödsinn; das steht aber allgemein bei vielem dran, was auch nur entfernt mit Component-Streaming zu tun hat.
Ein Hinweis noch: TReader/Writer verwenden zusätzlich zu den Daten jeweils noch eine 1-Byte-Kennung, die den Typ der Daten angibt. Damit hast du gleich eine Art Konsistenzprüfung, brauchst aber auch mehr Platz: WriteInteger() schreibt eben nicht 4 Byte, sondern 5.
catweasel hat folgendes geschrieben : | Und was ist die Obergrenze für die Buffergröße?. Hab dazu auch nichts gefunden. | Bis der RAM voll ist
Sinnvollerweise sollte man das an 4K-Schritten ausrichten, aber kommt natürlich auch drauf an wie viel du schreiben willst. Wenn deine ganze Datei nachher 10MByte groß wird lohnt sich ein großer Buffer (Windows nimmt gern 64k) eher als wenn die Datei sowieso nur 100 Byte wird. |
Also nachdem das mit den ersten Gehversuchen mit Streams ja ganz gut geklappt hat habe ich versucht das in mein aktuelles Projekt einfliessen zu lassen.
Und schon gibts Probleme. Es soll eine Liste von Objekten gelesen/gespeichert werden.
Ich habe den Quellcode mal beigefügt. Das Problem sieht so aus:
-Nur der erste "Record" wird gelesen, und dort auch nicht alle Felder.
-Alle weiteren Records sind leer (bis auf die Defaultwerte.
Es gibt keine Access Violations oder andere Fehler.
Die Anzahl der Records stimmt, nur wo sind die Daten
Ich hab den Programmablauf mitverfolgt. Da scheint irgendwie nichts zu fehlen. Trotzdem wird nix geladen/gespeichert.
Wäre echt toll wenn mir da jemand noch einmal weiterhelfen könnte.
Cheers,
Catweasel
PS: Nicht vom Arbeitstitel stören lassen. Ich bastel an einem Spiel im Stil von Civilization. Bis ich fertig bin wird mir sicher noch ein besserer Titel einfallen
Einloggen, um Attachments anzusehen!
_________________ Pommes werden schneller fertig wenn man sie vor dem Frittieren einige Minuten in siedendes Fett legt.
|
|
Keldorn
Beiträge: 2266
Erhaltene Danke: 4
Vista
D6 Prof, D 2005 Pro, D2007 Pro, DelphiXE2 Pro
|
Verfasst: Sa 19.01.13 10:23
Hallo,
kurz angeschaut, fang erstmal bei den Stringlisten an.
kurzes Demo hingeklatscht:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24:
| Var stream:Tstream; sl:Tstrings; begin stream:=TFileStream.Create('D:\test.dat',fmcreate); sl:=TStringList.Create; sl.Add('eintrag 1'); sl.Add('eintrag 2'); sl.SaveToStream(stream); sl.Clear; sl.Add('eintrag Neu'); sl.SaveToStream(stream); stream.free; sl.Free;
stream:=TFileStream.Create('D:\test.dat',fmOpenRead); sl:=TStringList.Create; sl.LoadFromStream(stream); Memo1.Lines.Assign(sl); Memo1.Lines.Add('========='); sl.LoadFromStream(stream); Memo1.Lines.AddStrings(sl); sl.Free; stream.Free; end; |
==> eintrag neu wird nach dem Laden der 1. stringliste zugeordnet, das 2. loadfromstream führt zu nix.
probier das einfach aus. Das Problem ist sl.loadfromstream gugg dir mal den soruce dazu an. Tstrings.savetostream und loadfromstream ist die Größe egal. Savetostream speichert keine "Größe" der stringlist und loadfromstream liest alles von der aktuellen StreamPosition bis zum ende. Wenn du danach noch was auslesen willst, steht nix mehr im stream drin .
Nimm nicht sl.savetostream sondern speichere z.B. den sl.text als string in den stream.
Gruß Frank
_________________ Lükes Grundlage der Programmierung: Es wird nicht funktionieren.
(Murphy)
|
|
catweasel
Beiträge: 487
Erhaltene Danke: 1
Win 7 64bit
Delphi 7 Second Sedition V7.2
|
Verfasst: Sa 19.01.13 12:58
Keldorn hat folgendes geschrieben : | Hallo,
kurz angeschaut, fang erstmal bei den Stringlisten an.
kurzes Demo hingeklatscht:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24:
| Var stream:Tstream; sl:Tstrings; begin stream:=TFileStream.Create('D:\test.dat',fmcreate); sl:=TStringList.Create; sl.Add('eintrag 1'); sl.Add('eintrag 2'); sl.SaveToStream(stream); sl.Clear; sl.Add('eintrag Neu'); sl.SaveToStream(stream); stream.free; sl.Free;
stream:=TFileStream.Create('D:\test.dat',fmOpenRead); sl:=TStringList.Create; sl.LoadFromStream(stream); Memo1.Lines.Assign(sl); Memo1.Lines.Add('========='); sl.LoadFromStream(stream); Memo1.Lines.AddStrings(sl); sl.Free; stream.Free; end; |
==> eintrag neu wird nach dem Laden der 1. stringliste zugeordnet, das 2. loadfromstream führt zu nix.
probier das einfach aus. Das Problem ist sl.loadfromstream gugg dir mal den soruce dazu an. Tstrings.savetostream und loadfromstream ist die Größe egal. Savetostream speichert keine "Größe" der stringlist und loadfromstream liest alles von der aktuellen StreamPosition bis zum ende. Wenn du danach noch was auslesen willst, steht nix mehr im stream drin .
Nimm nicht sl.savetostream sondern speichere z.B. den sl.text als string in den stream.
Gruß Frank |
Danke für den Tip. Ich dachte die TStringList.SaveToStream() wäre so bequem das die das alles mit der Grösse und so regelt. Ich habe das jetzt der TNameList Klasse hinzugefügt. Mit der Text Eigenschaft der Stringlist wollte ich jetzt nicht experimentieren da ich da schlechte Erfahrungen mit dem Delimiter gemacht habe.
Nun bekomme ich aber einen anderen Error.. "Bitmap is not valid".
Gibt es bei der TBitmap.SaveToStream etwas zu beachten, oder wo liegt der Fehlr jetzt
Cheers,
Catweasel
Einloggen, um Attachments anzusehen!
_________________ Pommes werden schneller fertig wenn man sie vor dem Frittieren einige Minuten in siedendes Fett legt.
|
|
Keldorn
Beiträge: 2266
Erhaltene Danke: 4
Vista
D6 Prof, D 2005 Pro, D2007 Pro, DelphiXE2 Pro
|
Verfasst: Sa 19.01.13 13:15
du hast doch die Enterprise, also auch die Sourcen. gugg doch einfach nach .
bitmap.loadfromstream:
Delphi-Quelltext 1:
| ReadStream(Stream, Stream.Size - Stream.Position); |
gleiches Problem.
evtl Abhilfe:
beim Speichern und Laden über einen memorystream gehen.
- memorystream erstellen
- Bitmap in den memstream reinspeichern
- in den richtigen stream die größe des memstreams speichern
- dann den memstream
beim Auslesen dann genau andersrum: nur die entsprechenden Bytes aus stream in den memstream auslesen und die Bitmap dann aus dem Memstream laden
Gruß Frank
_________________ Lükes Grundlage der Programmierung: Es wird nicht funktionieren.
(Murphy)
|
|
catweasel
Beiträge: 487
Erhaltene Danke: 1
Win 7 64bit
Delphi 7 Second Sedition V7.2
|
Verfasst: Sa 19.01.13 13:18
_________________ Pommes werden schneller fertig wenn man sie vor dem Frittieren einige Minuten in siedendes Fett legt.
|
|
catweasel
Beiträge: 487
Erhaltene Danke: 1
Win 7 64bit
Delphi 7 Second Sedition V7.2
|
Verfasst: Sa 19.01.13 13:38
Hi,
Hab das jetzt mal versucht. Das sieht so aus:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26:
| procedure TIconItem.LoadFromStream(AStream: TFileStream); var MemStream : TMemoryStream; Size : int64; begin inherited; MemStream := TMemoryStream.Create; Size := AStream.Read(Size,SizeOf(Size)); MemStream.Read(AStream,Size); FIcon.LoadFromStream(Memstream); MemStream.Free; end;
procedure TIconItem.SaveToStream(AStream: TFileStream); var MemStream : TMemoryStream; Size : int64; begin inherited; MemStream := TMemoryStream.Create; FIcon.SaveToStream(MemStream); Size := MemStream.Size; AStream.Write(Size,SizeOf(Size)); AStream.Write(MemStream,Size); MemStream.Free; end; |
Leider funktioniert es nicht Es werden nur wirre Daten eingelesen und das Programm "hängt sich auf" weil einige Listengrössen mit 7777864 eingelesen werden, etc.
Muss ich beim kopieren von Stream zu Stream nochwas beachten
Vielen Dank für die Hilfe
Cheers,
Catweasel
_________________ Pommes werden schneller fertig wenn man sie vor dem Frittieren einige Minuten in siedendes Fett legt.
|
|
jfheins
Beiträge: 918
Erhaltene Danke: 158
Win 10
VS 2013, VS2015
|
Verfasst: Sa 19.01.13 14:00
Hi,
ja kein Wunder dass das nicht klappt
Der Memorystrem ist ja ein Objekt, d.h. hier:
Delphi-Quelltext 1:
| AStream.Write(MemStream,Size); |
Schreibst du die Adresse des Objekts und noch ein paar Mülldaten in deinen Stream. Um an die tatsächlichen daten zu kommen hilft dir die Hilfe:
docwiki.embarcadero....mMemoryStream.Memory
also muss der Code irgendwie so lauten:
Delphi-Quelltext 1:
| AStream.Write(MemStream.Memory,Size); |
Ich glaube aber du musst den Pointer dann noch dereferenzieren - einfach mal ausprobieren
|
|
catweasel
Beiträge: 487
Erhaltene Danke: 1
Win 7 64bit
Delphi 7 Second Sedition V7.2
|
Verfasst: Sa 19.01.13 14:21
_________________ Pommes werden schneller fertig wenn man sie vor dem Frittieren einige Minuten in siedendes Fett legt.
|
|
catweasel
Beiträge: 487
Erhaltene Danke: 1
Win 7 64bit
Delphi 7 Second Sedition V7.2
|
Verfasst: Sa 19.01.13 19:11
Also, ich habe mir jetzt das ganze nochmal durch den Kopf gehen lassen und beschlossen die Pixel eizeln in den Stream zu packen. Das klappt auch ganz gut. Da ich mich mit Zeigern nicht so auskenne kann mir vielleicht noch jemand einen Tip geben.
Meine neue Bitmapklasse sieht so aus:
(nur die Streaming Methoden)
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33:
| procedure TStreamBitmap.LoadFromStream(AStream: TFileStream); var x,y,w,h : longint; Data : TColor; begin AStream.Read(w,SizeOf(w)); Width := w; AStream.Read(h,SizeOf(h)); Height := h; for y := 0 to h-1 do for x := 0 to w-1 do begin AStream.Read(Data,SizeOf(Data)); Canvas.Pixels[x,y] := Data; end; end;
procedure TStreamBitmap.SaveToStream(AStream: TFileStream); var x,y,w,h : longint; Data : TColor; begin w := Width; h := Height; AStream.Write(w,SizeOf(w)); AStream.Write(h,SizeOf(h)); for y := 0 to h-1 do for x := 0 to w-1 do begin Data := Canvas.Pixels[x,y]; AStream.Write(Data,SizeOf(Data)); end; end; |
Es müsste doch jetzt irgendwie möglich sein das per Scanline zu optimieren. Scanline(0) liefert mir doch einen Zeiger auf den ersten Pixel, oder nicht?
Kann ich dann nicht ab da (With*Heigth*BytesProPixel) Bytes lesen/schreiben?
Wenn ich das versuche klapp nichts
Cheers,
Catweasel
_________________ Pommes werden schneller fertig wenn man sie vor dem Frittieren einige Minuten in siedendes Fett legt.
|
|
Keldorn
Beiträge: 2266
Erhaltene Danke: 4
Vista
D6 Prof, D 2005 Pro, D2007 Pro, DelphiXE2 Pro
|
Verfasst: So 20.01.13 11:02
Hallo,
warum machst du Dir es so kompliziert. Zugriff auf pixel ist eh so grottenlangsam.
such doch auch hier im Forum, wenn Du Beispiele brauchst z.B.:
www.entwickler-ecke....copyfrom&view=df
(Beitrag von Viper)
Gruß Frank
_________________ Lükes Grundlage der Programmierung: Es wird nicht funktionieren.
(Murphy)
|
|
|