Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi MemoryStream in Filestream sichern - Datenschrott !? (https://www.delphipraxis.net/100317-memorystream-filestream-sichern-datenschrott.html)

moelski 26. Sep 2007 10:13


MemoryStream in Filestream sichern - Datenschrott !?
 
Moin !

Ich habe folgende Procedure:

Delphi-Quellcode:
procedure TForm10.dxBarButton6Click(Sender: TObject);
var fs: TFileStream;
    ms: TMemoryStream;
begin
  ms := TMemoryStream.Create;                    // Memory Stream für Objekt erzeugen
  fs := TFileStream.Create('test.dat',fmCreate); // Filestream erzeugen in dem alles abgelegt wird

  aqDockingManager1.SaveToStream(ms);            // aqDockingManager1 - Daten in dem Stream ablegen

  fs.WriteBuffer(ms, ms.Size);                    // aqDockingManager1 abspeichern

  fs.Free;
  ms.Free;
end;
Wenn ich das debugge dann kann ich feststellen das im MemoryStream MS alles sauber drin steht. Nämlich die Infos von DockingManager1. Wenn ich mir dann aber die Datei ansehe die durch TFileStream erzeugt wird, dann steht da was gänzlich anderes drin - nur Datenschrott.
Und ein Einlesen klappt dann logischerweise auch nicht mehr.

Kann mir jemand sagen wo mein Fehler liegt ? Warum wird der MemoryStream nicht sauber weggeschrieben ? :gruebel:

blackdrake 26. Sep 2007 10:17

Re: MemoryStream in Filestream sichern - Datenschrott !?
 
Hallo.

Write(a,b) oder WriteBuffera(a,b) verwendest du, wenn du den zu lesenden Inhalt der Länge b Bytes in Variable a speichern willst. "a" kann dann z.B. ein Integer sein. Strings muss man jedoch a[1] nennen. Aber in die MemoryStream-Variable kannst du nicht speichern!

Du kannst Inhalte von Streams mit "CopyFrom" rüberkopieren.

PS: Bitte Ressourcenschutzblöcke verwenden!

Delphi-Quellcode:
xyz := TStream.Create();
try
  // xyz...
finally
  xyz.free;
end;
Gruß
blackdrake

moelski 26. Sep 2007 10:22

Re: MemoryStream in Filestream sichern - Datenschrott !?
 
Moin !

Hmm, ich glaub ich steh auf der Leitung. Aber so tuts auch ned :

Delphi-Quellcode:
procedure TForm10.dxBarButton6Click(Sender: TObject);
var fs: TFileStream;
    ms: TMemoryStream;
begin
  ms := TMemoryStream.Create;                    // Memory Stream für Objekt erzeugen
  fs := TFileStream.Create('test.dat',fmCreate); // Filestream erzeugen in dem alles abgelegt wird

  aqDockingManager1.SaveToStream(ms);            // aqDockingManager1 - Daten in dem Stream ablegen

  fs.CopyFrom(ms, ms.Size);                    // aqDockingManager1 abspeichern

  fs.Free;
  ms.Free;
end;
Da kriege ich einen Stream Lesefehler :freak:

s-off 26. Sep 2007 10:27

Re: MemoryStream in Filestream sichern - Datenschrott !?
 
Hallo,
Zitat:

Zitat von moelski
Da kriege ich einen Stream Lesefehler

Zitat:

Zitat von blackdrake
Aber in die MemoryStream-Variable kannst du nicht speichern!

Delphi-Quellcode:
Procedure TForm1.Button1Click(Sender: TObject);
Var
   fs: TFileStream;
   ms: TMemoryStream;
Begin
   ms := TMemoryStream.Create;
   ms.LoadFromFile('C:\Download\Source.txt');
   fs := TFileStream.Create('C:\Download\Dest.txt', fmOpenReadWrite);
   fs.CopyFrom(ms, ms.Size);
   fs.Free;
   ms.Free;
End;

TeronG 26. Sep 2007 10:29

Re: MemoryStream in Filestream sichern - Datenschrott !?
 
Was spricht eigentlich gegen
Delphi-Quellcode:
ms.SaveToFile('filename');

also dann so in etwa:

Delphi-Quellcode:
procedure TForm10.dxBarButton6Click(Sender: TObject);
var    
  ms: TMemoryStream;
begin
  ms := TMemoryStream.Create;                    // Memory Stream für Objekt erzeugen
  try
    aqDockingManager1.SaveToStream(ms);          // aqDockingManager1 - Daten in dem Stream ablegen

    ms.SaveToFile('test.dat');                   // aqDockingManager1 abspeichern
  finally
    ms.Free;
  end;
end;

blackdrake 26. Sep 2007 10:31

Re: MemoryStream in Filestream sichern - Datenschrott !?
 
Hallo.

Unter Umständen musst du zwischen "SaveToStream" und "CopyFrom" die Position wieder auf 0 setzen.

Gruß
blackdrake

wicht 26. Sep 2007 10:33

Re: MemoryStream in Filestream sichern - Datenschrott !?
 
Eventuell musst du die Position des Streams vor CopyFrom() auch noch passend mit Seek() oder Position setzen.

Roter Kasten: Man, warum bin ich immer so spät...

Zitat:

If Count is 0, CopyFrom sets Source position to 0 before reading and then copies the entire contents of Source into the stream. If Count is greater than or less than 0, CopyFrom reads from the current position in Source.

moelski 26. Sep 2007 10:34

Re: MemoryStream in Filestream sichern - Datenschrott !?
 
Moin !

So gehts:
Delphi-Quellcode:
procedure TForm10.dxBarButton7Click(Sender: TObject);
Var
   fs: TFileStream;
   ms: TMemoryStream;
Begin
   ms := TMemoryStream.Create;
   //ms.LoadFromFile('E:\Documents and Settings\Administrator\My Documents\RAD Studio\Projekte\Unit1.pas');
   aqDockingManager1.SaveToStream(ms);
   fs := TFileStream.Create('ZTest.txt', fmCreate);
   ms.Position := 0;
   fs.CopyFrom(ms, ms.Size);
   fs.Free;
   ms.Free;
End;
Zitat:

Unter Umständen musst du nach "SaveToStream" die Position wieder auf 0 setzen.
Das war der Hinweis im Zusammenhang mit CopyFrom.

Nu rennt das ! Danke !

negaH 26. Sep 2007 10:34

Re: MemoryStream in Filestream sichern - Datenschrott !?
 
typischer Anfängerfehler.

Delphi-Quellcode:
aqDockingManager1.SaveToStream(ms);            // aqDockingManager1 - Daten in dem Stream ablegen
ms.position := 0;
fs.CopyFrom(ms, ms.Size);                    // aqDockingManager1 abspeichern
Wenn du irgendwas aus einem Stream liest oder schreibst, was passiert mit Stream.Position ?
Und wenn nun der Zielstream -> ms -> leer ist un man schreibt 1000 Bytes da hinein, wo steht ms.Position ? (Tipp .Positon = .Size)
Wenn du dann aus Stream -> ms lesen möchtest und .Positon = .Size, wieviele Bytes kann man dann daraus lesen ?

Diese Fragestellung kam schon oft in der DP vor.

Gruß Hagen

s-off 26. Sep 2007 10:35

Re: MemoryStream in Filestream sichern - Datenschrott !?
 
Zitat:

Zitat von wicht
Zitat:

If Count is 0, CopyFrom sets Source position to 0 before reading and then copies the entire contents of Source into the stream. If Count is greater than or less than 0, CopyFrom reads from the current position in Source.

Zitate aus der Hilfe bitte mit Quote-Tags versehen - ich dachte gerade schon die Delphi-Tags wären defekt :wink:

Edit: ah, schon selber gemerkt :-D

moelski 26. Sep 2007 10:35

Re: MemoryStream in Filestream sichern - Datenschrott !?
 
Nachtrag ...

Zitat:

Was spricht eigentlich gegen ms.SaveToFile('filename');
Soweit nix, aber ich mehrere Streams in einen kopieren. Und da geht das glaube ich nicht so einfach.

mschaefer 26. Sep 2007 11:07

Re: MemoryStream in Filestream sichern - Datenschrott !?
 
Das mit den Streams ist allgemeiner verwendbar. Man kann so ein normales Memo auch in ein Blobfeld einer Datenbank schreiben in dem man es in den Blobstream des Feldes schreibt. Wenn man das Prinzip hat, braucht man weniger anderes lernen,...

Grüße // Martin

Muetze1 26. Sep 2007 11:35

Re: MemoryStream in Filestream sichern - Datenschrott !?
 
Zusammenfassend:

1. Streamposition vorher zurücksetzen, da Schreib- und Lesezugriffe den Positionszeiger versetzen.
2. CopyFrom() benutzen, da es sich um ein Objekt handelt und nicht um direkte Daten. Aber warum nutzt hier keiner (wie schon hier gepostet) als zweiten Parameter die 0? Schliesslich soll alles kopiert werden.
3. Akzeptiert aqDockingManager1.SaveToStream() wirklich nur einen MemoryStream oder doch vllt. einfach nur TStream? Weil warum nicht gleich den TFileStream angeben?

Wenn 3. nicht zutrifft:
Delphi-Quellcode:
procedure TForm10.dxBarButton7Click(Sender: TObject);
Var
   fs: TFileStream;
   ms: TMemoryStream;
Begin
   ms := TMemoryStream.Create;
   try
     aqDockingManager1.SaveToStream(ms);
   
     fs := TFileStream.Create('ZTest.txt', fmCreate);
     try
       fs.CopyFrom(ms, 0);
     finally
       fs.Free;
     end;
   finally
     ms.Free;
   end;
End;
Wenn 3. zutrifft:
Delphi-Quellcode:
procedure TForm10.dxBarButton7Click(Sender: TObject);
Var
   fs: TFileStream;
Begin
   fs := TFileStream.Create('ZTest.txt', fmCreate);
   try
     aqDockingManager1.SaveToStream(fs);
   finally
     fs.Free;
   end;
End;

moelski 26. Sep 2007 11:36

Re: MemoryStream in Filestream sichern - Datenschrott !?
 
Moin !

Hätte da noch ne Frage ...
Mein Stream hat nun 2 Elemente. Am Anfang ein Integerwert der die Grösse des folgendes Objekts enthält.

Nur wie lese ich jetzt diesen Integerwert wieder aus?
Delphi-Quellcode:
Groesse := fs.ReadBuffer(Groesse, SizeOf(Groesse));
... liefert mir ja 4 weil es 4 Byte sind.

Nur wie komme ich nun wieder an die Zahl ?

moelski 26. Sep 2007 11:38

Re: MemoryStream in Filestream sichern - Datenschrott !?
 
@Thomas:

Nuna ich will ja eben nicht nur die Docking Sache in den Stream packen sondern auch noch den BarManager von DevExpress. Das kann man evtl. auch hintereinander einfach wegschreiben, aber beim Lesen könnte es dann stressig werden, oder?

Wobei ich ja beim Laden auch noch Stress habe :roll: (siehe Post vor diesem) ...

Muetze1 26. Sep 2007 11:56

Re: MemoryStream in Filestream sichern - Datenschrott !?
 
Zitat:

Zitat von moelski
Delphi-Quellcode:
Groesse := fs.ReadBuffer(Groesse, SizeOf(Groesse));

Hmm, warum sollte die Funktion 3 mal den gleichen Wert brauchen? Schonmal in die Hilfe geschaut? Was braucht sie, was gibt sie zurück?

Zitat:

Zitat von moelski
Nuna ich will ja eben nicht nur die Docking Sache in den Stream packen sondern auch noch den BarManager von DevExpress. Das kann man evtl. auch hintereinander einfach wegschreiben, aber beim Lesen könnte es dann stressig werden, oder?

Zum einen: Klar, das kannst du auch nacheinander wegschreiben. Und auch musst du nicht über den Memorystream gehen. Und egal wie du es in die Datei beförderst, dass Auslesen wäre unabhängig davon schwierig.

Du müsstest dir ein Format ausdenken um dann später beim einlesen wieder die gespeicherten Teile auseinander zu halten und laden zu können.

moelski 26. Sep 2007 12:03

Re: MemoryStream in Filestream sichern - Datenschrott !?
 
Moin !

Zitat:

Du müsstest dir ein Format ausdenken um dann später beim einlesen wieder die gespeicherten Teile auseinander zu halten und laden zu können.
Eben drum ja erst die Grösse des folgendesn Objekts als Integer wegschreiben. Die Grösse auslesen um dann den Streampart zu lesen. Danach wieder Grösse aus nächstem Integer lesen und den nächsten Part lesen. So braucht man kein Datenformat zu definieren.

Zitat:

Hmm, warum sollte die Funktion 3 mal den gleichen Wert brauchen? Schonmal in die Hilfe geschaut?
Schon, aber ich kome an der Stelle nicht weiter.

Wenn ich nach der Hilfe gehe ..
Zitat:

Mit ReadBuffer wird die in Count angegebene Anzahl Bytes aus dem Stream in den Buffer (Puffer) gelesen, wenn die Anzahl der Bytes bekannt und nicht variabel ist, beispielsweise beim Einlesen von Strukturen. Intern wird ReadBuffer zum Laden und Kopieren aus einem Stream eingesetzt.
Sollte es ja so schon funktionieren:
fs.ReadBuffer(Groesse, SizeOf(Integer));

Aber das tut es leider nicht.

Groesse hat bei mir einen Wert von 5523860. Vor und nach dem Aufruf von ReadBuffer :gruebel:

Muetze1 26. Sep 2007 12:08

Re: MemoryStream in Filestream sichern - Datenschrott !?
 
Zitat:

Zitat von moelski
Zitat:

Du müsstest dir ein Format ausdenken um dann später beim einlesen wieder die gespeicherten Teile auseinander zu halten und laden zu können.
Eben drum ja erst die Grösse des folgendesn Objekts als Integer wegschreiben. Die Grösse auslesen um dann den Streampart zu lesen. Danach wieder Grösse aus nächstem Integer lesen und den nächsten Part lesen. So braucht man kein Datenformat zu definieren.

Damit hast du schon ein Datenformat definiert. Das ist schon ein Dateiformat - und mehr ist auch nicht nötig.

Zitat:

Zitat von moelski
Sollte es ja so schon funktionieren:
Delphi-Quellcode:
fs.ReadBuffer(Groesse, SizeOf(Integer));
Aber das tut es leider nicht.

Das ist ein anderer Code als zuvor gepostet. Wo liegt der Unterschied?

Zitat:

Zitat von moelski
Groesse hat bei mir einen Wert von 5523860. Vor und nach dem Aufruf von ReadBuffer :gruebel:

Sicher, dass nicht vielleicht dieser Wert im Stream steht? Oder bist du vielleicht an einer anderen Stelle im Stream als der, wo du damals eine Zahl hineingeschrieben hast? Und vor allem: was hast du denn hineingeschrieben?

moelski 26. Sep 2007 12:18

Re: MemoryStream in Filestream sichern - Datenschrott !?
 
Moin !

Au Backe .... :wall:

Ich habe beim Speichern zwar den Wert weggespeichert, aber nicht die wirklich Grösse (wie gross der Stream ist) diesem Wert zugewiesen. Also hat er irgend einen Pseudowert weggeschrieben :angel2:

Nu habe ich auch einen richtigen Wert beim Auslesen :cheers:
So nun mal sehen ob ich denn auch meinen Stream wieder bekomme :tongue:

mschaefer 26. Sep 2007 12:20

Re: MemoryStream in Filestream sichern - Datenschrott !?
 
Ein prinzipieller Weg wäre einen Header
vorwegzuschreiben. Nehmen wir an Du hast foldende Struktur:

1. Longint:
= Version des Streams

2. Longint:
= N. Anzahl der Datensätze

3. Longint - N. Longint :
= Startpostionen der Datensätze

Von (N+1 Longintlänge) bis Ende
Daten

Wäre eine Möglichkeit, anderes geht aber auch.

Grüße // Martin

moelski 26. Sep 2007 12:24

Re: MemoryStream in Filestream sichern - Datenschrott !?
 
Moin !

Es tut nun :thumb:

Ich poste gleich mal meine Lösung. Vielleicht nutzt es ja wem anderes später mal was.

Danke derweil an alle für die Hilfe. :hi:


Alle Zeitangaben in WEZ +1. Es ist jetzt 22:12 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 by Thomas Breitkreuz