TFileStream und TMemo

Rund um die LCL und andere Komponenten
Antworten
Mathias
Beiträge: 7317
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

TFileStream und TMemo

Beitrag von Mathias »

Ich habe 2 Memos und eine ComboBox.
Wen ich save und anschliessend load klicke, habe ich im Memo1 den alten Inhalt von Memo1 und Memo2.
Memo2 und ComboBox bleibt leer.
Wieso ?

Code: Alles auswählen

type TfloatArray=array[0..9]of single;
 
procedure TForm1.saveClick(Sender: TObject);
var
  stream:TFileStream;
  fa:TfloatArray;
begin
  stream:=TFileStream.Create('test.bin',fmCreate);
  stream.Write(fa, SizeOf(fa));
  Memo1.Lines.SaveToStream(stream);
  Memo1.Clear;
  Memo2.Lines.SaveToStream(stream);
  Memo2.Clear;
  ComboBox1.Items.SaveToStream(stream);
  ComboBox1.Clear;
  stream.Free;
end;
 
procedure TForm1.loadClick(Sender: TObject);
var
  stream:TFileStream;
  fa:TfloatArray;
begin
  stream:=TFileStream.Create('test.bin',fmOpenRead);
  stream.Read(fa, SizeOf(fa));
  Memo1.Lines.LoadFromStream(stream);
  Memo2.Lines.LoadFromStream(stream);
  ComboBox1.Items.LoadFromStream(stream);
  stream.Free;
end; 
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Michl
Beiträge: 2513
Registriert: Di 19. Jun 2012, 12:54

Re: TFileStream und TMemo

Beitrag von Michl »

MMn müsstest du einfach die Position entsprechend setzen. Ich habe das mal so probiert, mit einem leeren Projekt. Es wird alles wie erwartet geladen:

Code: Alles auswählen

procedure TForm1.loadClick(Sender: TObject);
var
  stream:TFileStream;
  fa:TfloatArray;
begin
  stream:=TFileStream.Create('test.bin',fmOpenRead);
  stream.Read(fa, SizeOf(fa));
  Memo1.Lines.LoadFromStream(stream);
  Stream.Position:=SizeOf(fa);  
  Memo2.Lines.LoadFromStream(stream);
  Stream.Position:=SizeOf(fa);   
  ComboBox1.Items.LoadFromStream(stream);
  stream.Free;
end;

Code: Alles auswählen

type
  TLiveSelection = (lsMoney, lsChilds, lsTime);
  TLive = Array[0..1] of TLiveSelection;  

Warf
Beiträge: 2306
Registriert: Di 23. Sep 2014, 17:46
OS, Lazarus, FPC: Win10 | Linux
CPU-Target: x86_64

Re: TFileStream und TMemo

Beitrag von Warf »

Das problem ist LoadFromStream ließt bis EOF, un da du die Zeilen einfach hinter einander klatschst wird einfach die gesamte Datei in das erste Memo gelesen, und nichts bleibt mehr für die anderen Komponenten übrig. Um das zu umgehen musst du die Größe der Texte speichern Beispiel:

Code: Alles auswählen

procedure SaveLinesToStream(sl: TStrings; str: TStream);
var buff: Cardinal;
begin
  if not Assigned(str) then
    exit;
  buff:=Length(sl.Text);
  str.Write(buff, SizeOf(buff));
  sl.SaveToStream(str);
end;
 
procedure LoadLinesFromStream(sl: TStrings; str: TStream);
var buff: Cardinal;
  ms: TMemoryStream;
begin
  if not Assigned(str) then
    exit;
  ms:=TMemoryStream.Create;
  try
    str.Read(buff, SizeOf(buff));
    ms.CopyFrom(str, buff);
    ms.Seek(0, soFromBeginning);
    sl.LoadFromStream(ms);
  finally
    ms.Free;
  end;
end;     

Mathias
Beiträge: 7317
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: TFileStream und TMemo

Beitrag von Mathias »

Irgendwie sehe ich da keinen Sinn dahinter.
Ist bei einem Stream nicht die Idee dahinter, das man mehrere Sachen auf einmal speichern kann ?

Bei der FPC-Quelle wird tatsächlich ohne Längen-Angabe gespeichert.

Code: Alles auswählen

Procedure TStrings.SaveToStream(Stream: TStream);
Var
  S : String;
begin
  S:=Text;
  if S = '' then Exit;
  Stream.WriteBuffer(Pointer(S)^,Length(S));
end;    
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

wp_xyz
Beiträge: 5456
Registriert: Fr 8. Apr 2011, 09:01

Re: TFileStream und TMemo

Beitrag von wp_xyz »

Die Hauptanwendung von TStrings.SavetoStream verwendet den Stream für sich allein, daher ist die Längeninformation unnötig.

Mathias
Beiträge: 7317
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: TFileStream und TMemo

Beitrag von Mathias »

Du meinst es kommt von da her:

Code: Alles auswählen

Procedure TStrings.SaveToFile(const FileName: string);
 
Var TheStream : TFileStream;
 
begin
  TheStream:=TFileStream.Create(FileName,fmCreate);
  try
    SaveToStream(TheStream);
  finally
    TheStream.Free;
  end;
end;  
Jetzt sehe ich den Sinn, bei speichern einer Text-Datei sind Längen-Angaben ein Müll.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Antworten