Autor Beitrag
Martok
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 3661
Erhaltene Danke: 604

Win 8.1, Win 10 x64
Pascal: Lazarus Snapshot, Delphi 7,2007; PHP, JS: WebStorm
BeitragVerfasst: So 13.01.13 20:23 
user profile iconcatweasel hat folgendes geschrieben Zum zitierten Posting springen:
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.

user profile iconcatweasel hat folgendes geschrieben Zum zitierten Posting springen:
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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 487
Erhaltene Danke: 1

Win 7 64bit
Delphi 7 Second Sedition V7.2
BeitragVerfasst: Sa 19.01.13 00:31 
user profile iconMartok hat folgendes geschrieben Zum zitierten Posting springen:
user profile iconcatweasel hat folgendes geschrieben Zum zitierten Posting springen:
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.

user profile iconcatweasel hat folgendes geschrieben Zum zitierten Posting springen:
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. :eyes:


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 :wink:
Einloggen, um Attachments anzusehen!
_________________
Pommes werden schneller fertig wenn man sie vor dem Frittieren einige Minuten in siedendes Fett legt.
Keldorn
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 2266
Erhaltene Danke: 4

Vista
D6 Prof, D 2005 Pro, D2007 Pro, DelphiXE2 Pro
BeitragVerfasst: Sa 19.01.13 10:23 
Hallo,

kurz angeschaut, fang erstmal bei den Stringlisten an.

kurzes Demo hingeklatscht:
ausblenden 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 487
Erhaltene Danke: 1

Win 7 64bit
Delphi 7 Second Sedition V7.2
BeitragVerfasst: Sa 19.01.13 12:58 
user profile iconKeldorn hat folgendes geschrieben Zum zitierten Posting springen:
Hallo,

kurz angeschaut, fang erstmal bei den Stringlisten an.

kurzes Demo hingeklatscht:
ausblenden 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 2266
Erhaltene Danke: 4

Vista
D6 Prof, D 2005 Pro, D2007 Pro, DelphiXE2 Pro
BeitragVerfasst: Sa 19.01.13 13:15 
du hast doch die Enterprise, also auch die Sourcen. gugg doch einfach nach ;-).

bitmap.loadfromstream:
ausblenden 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 487
Erhaltene Danke: 1

Win 7 64bit
Delphi 7 Second Sedition V7.2
BeitragVerfasst: Sa 19.01.13 13:18 
user profile iconKeldorn hat folgendes geschrieben Zum zitierten Posting springen:
du hast doch die Enterprise, also auch die Sourcen. gugg doch einfach nach ;-).

bitmap.loadfromstream:
ausblenden 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


Werd ich gleich mal testen... Und ich muss mein Profil mal updaten... Ich benutz zur Zeit Delphi 7 Second Edition :)

Cheers,
Catweasel

_________________
Pommes werden schneller fertig wenn man sie vor dem Frittieren einige Minuten in siedendes Fett legt.
catweasel Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 487
Erhaltene Danke: 1

Win 7 64bit
Delphi 7 Second Sedition V7.2
BeitragVerfasst: Sa 19.01.13 13:38 
Hi,


Hab das jetzt mal versucht. Das sieht so aus:

ausblenden 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
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 918
Erhaltene Danke: 158

Win 10
VS 2013, VS2015
BeitragVerfasst: Sa 19.01.13 14:00 
Hi,
ja kein Wunder dass das nicht klappt :twisted:

Der Memorystrem ist ja ein Objekt, d.h. hier:
ausblenden 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:
ausblenden Delphi-Quelltext
1:
AStream.Write(MemStream.Memory,Size);					

Ich glaube aber du musst den Pointer dann noch dereferenzieren - einfach mal ausprobieren :wink:
catweasel Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 487
Erhaltene Danke: 1

Win 7 64bit
Delphi 7 Second Sedition V7.2
BeitragVerfasst: Sa 19.01.13 14:21 
user profile iconjfheins hat folgendes geschrieben Zum zitierten Posting springen:
Hi,
ja kein Wunder dass das nicht klappt :twisted:

Der Memorystrem ist ja ein Objekt, d.h. hier:
ausblenden 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:
ausblenden Delphi-Quelltext
1:
AStream.Write(MemStream.Memory,Size);					

Ich glaube aber du musst den Pointer dann noch dereferenzieren - einfach mal ausprobieren :wink:


JA. Ich hatte verdrängt das Objekte "nur" Referenzen sind :oops:
Hmmm. Aber auf was muss ich das dereferenzieren. Ich habe mit Pointern kaum Erfahrung.
TMemoryStream.Memory ist vom Typ Pointer. Aber dem FileStream fehlt das. Wie soll ich dann den Punkt zum lesen referenzieren. Vielleicht habe ich auch nur etwas mit den Pointern nicht verstanden.... Momentan komme ich hier echt nicht weiter :?

ausblenden 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:
27:
28:
29:
30:
procedure TIconItem.LoadFromStream(AStream: TFileStream);
var
MemStream : TMemoryStream;
p : Pointer;
Size : int64;
begin
  inherited;
MemStream := TMemoryStream.Create;
Size := AStream.Read(Size,SizeOf(Size));
p := AStream.Memory;     // FileStream kennt kein Memory
MemStream.Read(p^,Size);
FIcon.LoadFromStream(Memstream.Memory);
MemStream.Free;
end;

procedure TIconItem.SaveToStream(AStream: TFileStream);
var
MemStream : TMemoryStream;
p : Pointer;
Size : int64;
begin
  inherited;
MemStream := TMemoryStream.Create;
FIcon.SaveToStream(MemStream);
Size := MemStream.Size;
p := MemStream.Memory;
AStream.Write(Size,SizeOf(Size));
AStream.Write(p^,Size);
MemStream.Free;
end;


Echst super Eure Hilfe :D
Ich habe gerade gesehen es gibt eine CopyFrom() Prozedur. Lässt sich damit etwas anfangen?


Cheers,
Catweasel

_________________
Pommes werden schneller fertig wenn man sie vor dem Frittieren einige Minuten in siedendes Fett legt.
catweasel Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 487
Erhaltene Danke: 1

Win 7 64bit
Delphi 7 Second Sedition V7.2
BeitragVerfasst: 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)

ausblenden volle Höhe 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:
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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 2266
Erhaltene Danke: 4

Vista
D6 Prof, D 2005 Pro, D2007 Pro, DelphiXE2 Pro
BeitragVerfasst: 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)