AGB  ·  Datenschutz  ·  Impressum  







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

Daten per Streams in Datei schreiben

Ein Thema von delphinub23 · begonnen am 22. Jul 2014 · letzter Beitrag vom 23. Jul 2014
Antwort Antwort
Seite 1 von 2  1 2      
delphinub23

Registriert seit: 27. Okt 2010
Ort: Chemnitz
110 Beiträge
 
Delphi XE3 Professional
 
#1

Daten per Streams in Datei schreiben

  Alt 22. Jul 2014, 10:51
Hallo Leute!

Gleich vorweg: Ich habe noch nicht oft mit Streams gearbeitet.

Ich möchte per Stream verschiedene Daten in eine Datei schreiben und wieder lesen können.
Im Detail sind die Daten Klassen, welche irgendwelche Informationen enthalten (Beschreibung, etc...).
Die Klassen kennen sich untereinander nicht. Somit muss ich die Daten im Stream anhand von Headern identifizieren können.

In meiner Vorstellung sieht das so aus:
|_HeaderA_|_DataA___________|_HeaderB_|_DataB_____ ______|_HeaderC_|_DataC___________|

Nur leider habe ich keine Idee, wie ich das umsetzen kann
So sieht mein Testframe aus:

Delphi-Quellcode:
unit FmStreamOperations;

interface

uses
  Winapi.Windows,
  Winapi.Messages,
  System.SysUtils,
  System.Variants,
  System.Classes,

  Vcl.Graphics,
  Vcl.Controls,
  Vcl.Forms,
  Vcl.Dialogs,
  Vcl.StdCtrls;

type
  (*
    This is the first record that should be saved to a file
      most important properties:
      @ version field that can be interpreted from reader classes
      @ conentlen field when the record ends and the next record begins

    NOTE: packed record because the memory alignment of regular records are
          subject to change between releases
  *)

  TDummyHeaderA = packed record
    // after structure changes increment this
    Version: Integer;
    // position of begin of content
    Pos: Integer;
    // Integer should be enough to prevent to low allocation for the content
    Len: LongInt;
    // do not use dynamic length; ShortString (String[255]) instead of String
    HeaderType: ShortString;
  end;



  (*
    This is the second record that should be saved to a file
      most important properties:
      @ version field that can be interpreted from reader classes
      @ conentlen field when the record ends and the next record begins

    NOTE: packed record because the memory alignment of regular records are
          subject to change between releases
  *)

  TDummyHeaderB = packed record
    // after structure changes increment this
    Version: Integer;
    // position of begin of content
    Pos: Integer;
    // Integer should be enough to prevent to low allocation for the content
    Len: Integer;
    // do not use dynamic length; ShortString (String[255]) instead of String
    HeaderType: ShortString;
  end;



  (*
    This is the third record that should be saved to a file
      most important properties:
      @ version field that can be interpreted from reader classes
      @ conentlen field when the record ends and the next record begins

    NOTE: packed record because the memory alignment of regular records are
          subject to change between releases
  *)

  TDummyHeaderC = packed record
    // after structure changes increment this
    Version: Integer;
    // position of begin of content
    Pos: Integer;
    // Integer should be enough to prevent to low allocation for the content
    Len: Integer;
    // do not use dynamic length; ShortString (String[255]) instead of String
    HeaderType: ShortString;
  end;



  (*
    This is a dummy class for testing the header TDatasetHeaderA
  *)

  TDummyA = class(TPersistent)
  private
    FValueA: Integer;
    FValueB: string;
    FValueC: Boolean;
  public
    constructor Create;
    destructor Destroy; override;
    property ValueA: Integer read FValueA write FValueA;
    property ValueB: string read FValueB write FValueB;
    property ValueC: Boolean read FValueC write FValueC;
  end;



  (*
    This is a dummy class for testing the header TDatasetHeaderB
  *)

  TDummyB = class(TPersistent)
  private
    FValueA: Int64;
    FValueB: ShortString;
    FValueC: PChar;
  public
    constructor Create;
    destructor Destroy; override;
    property ValueA: Int64 read FValueA write FValueA;
    property ValueB: ShortString read FValueB write FValueB;
    property ValueC: PChar read FValueC write FValueC;
  end;



  (*
    This is a dummy class for testing the header TDatasetHeaderC
  *)

  TDummyC = class(TPersistent)
  private
    FValueA: SmallInt;
    FValueB: Char;
    FValueC: Double;
  public
    constructor Create;
    destructor Destroy; override;
    property ValueA: SmallInt read FValueA write FValueA;
    property ValueB: Char read FValueB write FValueB;
    property ValueC: Double read FValueC write FValueC;
  end;



  (*
    Testframe form
  *)

  TFmTestframe = class(TForm)
    ButtonSave: TButton;
    ButtonLoad: TButton;
    procedure ButtonSaveClick(Sender: TObject);
    procedure ButtonLoadClick(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;



  (*
    constants
  *)

  const C_FILE_EXT = 'bin';
  const C_FILE_LOC = 'C:\';
var
  FmTestframe: TFmTestframe;

implementation

{$R *.dfm}

procedure TFmTestframe.ButtonLoadClick(Sender: TObject);
var
  Stream: TFileStream;
  FileName: string;
  HeaderA: TDummyHeaderA;
  DataA: TDummyA;
begin
  // Try to load TDummyHeaderA & TDummyA from file via stream to the objects
  FileName :=
    Format('%s.ExampleFileWrittenWithStream.%s', [C_FILE_LOC, C_FILE_EXT]);
  // !! don't forget to check if the file exist and is accessable in production builds
  Stream := TFileStream.Create(FileName, fmOpenRead);
  try
    // Stream.Read(...) <----- ??? What to do here?
  finally
    FreeAndNil(Stream);
  end;
end;



procedure TFmTestframe.ButtonSaveClick(Sender: TObject);
var
  Stream: TFileStream;
  HeaderA: TDummyHeaderA;
  DataA: TDummyA;
  FileName: string;
begin
  // Try it with TDummyHeaderA & TDummyA first
  // Fill TDummyHeaderA with data
  HeaderA.Version := 1;
  HeaderA.Pos := 0; { replace with start point of the content??? }
  HeaderA.Len := 0; { replace with the length of the content??? }
  HeaderA.HeaderType := '[Type] Dummy Header A';

  // TDummyA is filled with dummy data by the constructor
  DataA := TDummyA.Create;
  try
    // Try to save TDummyHeaderA & TDummyA into file via stream
    FileName :=
      Format('%s.ExampleFileWrittenWithStream.%s', [C_FILE_LOC, C_FILE_EXT]);
    // !! don't forget to check if the file exist and is accessable in production builds
    Stream := TFileStream.Create(FileName, fmCreate);
    try
      // Stream.Write(HeaderA, ...) <----- ??? What to do here?
      // ...
      // ..
      // .
    finally
      FreeAndNil(Stream);
    end;
  finally
    FreeAndNil(DataA);
  end;
end;



{ TDummyA }

constructor TDummyA.Create;
begin
  FValueA := 1;
  FValueB := 'DummyA Example Text';
  FValueC := True;
end;

destructor TDummyA.Destroy;
begin
  inherited;
end;



{ TDummyB }

constructor TDummyB.Create;
begin
  FValueA := 9823323232313;
  FValueB := 'Dummy B';
  FValueC := PChar('Pointer to string test');
end;

destructor TDummyB.Destroy;
begin
  inherited;
end;



{ TDummyC }

constructor TDummyC.Create;
begin
  FValueA := -1;
  FValueB := 'C';
  FValueC := 3.14;
end;

destructor TDummyC.Destroy;
begin
  inherited;
end;

end.
Es wäre nett, wenn mir jemand Hilfestellung geben könnte

Geändert von delphinub23 (22. Jul 2014 um 10:56 Uhr)
  Mit Zitat antworten Zitat
Photoner

Registriert seit: 6. Dez 2012
Ort: Nürnberg
103 Beiträge
 
Delphi 10.1 Berlin Starter
 
#2

AW: Daten per Streams in Datei schreiben

  Alt 22. Jul 2014, 11:05
Schau die mal TWriter an. Sollte genau das tun was du willst.
Beispiel:

Delphi-Quellcode:
    
procedure TIrgendwas.SaveToStream(AStream : TStream);
var
  Writer : TWriter;
begin
  Writer := TWriter.Create(AStream,$10000000);
  try
    Writer.WriteString('<BEGINVERSION>');
    Writer.WriteInteger(majorVer);
    Writer.WriteInteger(minorVer);
    Writer.WriteString('<ENDVERSION>');
    Writer.FlushBuffer;
  finally
    Writer.Free;
  end;
end;
Chris
  Mit Zitat antworten Zitat
Benutzerbild von Aphton
Aphton

Registriert seit: 31. Mai 2009
1.198 Beiträge
 
Turbo Delphi für Win32
 
#3

AW: Daten per Streams in Datei schreiben

  Alt 22. Jul 2014, 11:23
Geht es nun konkret um eine bestimmte Architektur oder eher darum, wie du nun mit der TFileStream Klasse arbeitest?!
das Erkennen beginnt, wenn der Erkennende vom zu Erkennenden Abstand nimmt
MfG
  Mit Zitat antworten Zitat
delphinub23

Registriert seit: 27. Okt 2010
Ort: Chemnitz
110 Beiträge
 
Delphi XE3 Professional
 
#4

AW: Daten per Streams in Datei schreiben

  Alt 22. Jul 2014, 11:30
Zitat:
Schau die mal TWriter an. Sollte genau das tun was du willst.
Danke ich schau mal rein!

Zitat:
Geht es nun konkret um eine bestimmte Architektur oder eher darum, wie du nun mit der TFileStream Klasse arbeitest?!
Es geht um die oben abgebildete Architektur.
  Mit Zitat antworten Zitat
Photoner

Registriert seit: 6. Dez 2012
Ort: Nürnberg
103 Beiträge
 
Delphi 10.1 Berlin Starter
 
#5

AW: Daten per Streams in Datei schreiben

  Alt 22. Jul 2014, 11:35
Der Vollständigkeit halber:

Mit TReader liest du das ganze wieder ein.
Chris
  Mit Zitat antworten Zitat
Klaus01

Registriert seit: 30. Nov 2005
Ort: München
5.768 Beiträge
 
Delphi 10.4 Sydney
 
#6

AW: Daten per Streams in Datei schreiben

  Alt 22. Jul 2014, 11:57
Hallo,

warum hast Du die Header (a..c) dreimal als Typ deklariert?
Die Typen unterscheiden, so weit ich das gesehen habe, nicht.

Grüße
Klaus
Klaus
  Mit Zitat antworten Zitat
delphinub23

Registriert seit: 27. Okt 2010
Ort: Chemnitz
110 Beiträge
 
Delphi XE3 Professional
 
#7

AW: Daten per Streams in Datei schreiben

  Alt 22. Jul 2014, 13:26
Zitat:
warum hast Du die Header (a..c) dreimal als Typ deklariert?
Die Typen unterscheiden, so weit ich das gesehen habe, nicht.
Ja. Da hast du Recht. Das sind erstmal nur fiktive Typen.
Die tatsächlichen Typen werden sich unterscheiden.

Ich habe das es nun mit dem TWriter/TReader probiert und siehe da...es funktioniert!
Nun stellt sich mir die Frage, wie ich z. B. nur den Header C und dessen Content auslesen kann?
  Mit Zitat antworten Zitat
mjustin

Registriert seit: 14. Apr 2008
3.006 Beiträge
 
Delphi 2009 Professional
 
#8

AW: Daten per Streams in Datei schreiben

  Alt 22. Jul 2014, 13:37
Delphi-Quellcode:
    
  Writer := TWriter.Create(AStream,$10000000);
Diese Zeile erzeugt eine TWriter Instanz, aber was machen die zehn Millionen Dollar?
Michael Justin
  Mit Zitat antworten Zitat
Benutzerbild von Aphton
Aphton

Registriert seit: 31. Mai 2009
1.198 Beiträge
 
Turbo Delphi für Win32
 
#9

AW: Daten per Streams in Datei schreiben

  Alt 22. Jul 2014, 14:32
Insgeheimer Bankeinzug bei Instanzierung..
das Erkennen beginnt, wenn der Erkennende vom zu Erkennenden Abstand nimmt
MfG
  Mit Zitat antworten Zitat
Klaus01

Registriert seit: 30. Nov 2005
Ort: München
5.768 Beiträge
 
Delphi 10.4 Sydney
 
#10

AW: Daten per Streams in Datei schreiben

  Alt 22. Jul 2014, 14:38
Ich habe das es nun mit dem TWriter/TReader probiert und siehe da...es funktioniert!
Nun stellt sich mir die Frage, wie ich z. B. nur den Header C und dessen Content auslesen kann?
Dann musst Du mit seek zur der Position des HeaderC springen.
Die Position wäre dann: 0+sizeOf(HeaderA)+sizeOf(dataA)+sizeOf(HeaderB)+si zeOf(dataB).

Header.len gibt das die Größe des Datenpaketes an?
Wenn ja, dann kannst Du auch HeaderX.len anstelle von sizeOf(dataX) benutzen.

Grüße
Klaus
Klaus
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


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 00:53 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