Home » Tutorials » Datenspeicherung » Binäre Dateien

Binäre Dateien

TKontakt.LoadFromBinaryTag

Ein Kontakt soll selbst in der Lage sein seine Daten aus dem Zwischenformat zu lesen. Dazu implementieren wir hier die Methode LoadFromBinaryTag.

TKontakt = class
  ...
  public
  ...
    procedure LoadFromBinaryTag(Tag: TRakBinaryTag);
    procedure SaveToBinaryTag(Tag: TRakBinaryTag);
  ...
  end;

procedure TKontakt.LoadFromBinaryTag(Tag: TRakBinaryTag);
var
  Attr: TRakBinaryAttribute;
begin
  FVorname := Tag.AttributeAsString('Vorname', '');
  FNachname := Tag.AttributeAsString('Nachname', '');
  FEmail := Tag.AttributeAsString('Email', '');
  FTelArbeit := Tag.AttributeAsString('TelArbeit', '');
  FStrasse := Tag.AttributeAsString('Strasse', '');
  FHandy := Tag.AttributeAsString('Handy', '');
  FTelPrivat := Tag.AttributeAsString('TelPrivat', '');
  FOrt := Tag.AttributeAsString('Ort', '');

  FPrivat := Tag.AttributeAsBoolean('Privat', true);

  Attr := Tag.AttributeByName('Geburtstag');
  FGeburtstagNichtVersorgt := not(Attr is TRakBinaryDateTime) or Attr.IsNull;
  if not FGeburtstagNichtVersorgt then
    FGeburtstag := TRakBinaryDateTime(Attr).Value;

  Attr := Tag.AttributeByName('PLZ');
  FPLZNichtVersorgt := not(Attr is TRakBinaryLongint) or Attr.IsNull;
  if not FPLZNichtVersorgt then
    FPLZ := TRakBinaryLongint(Attr).Value;

  Attr := Tag.AttributeByName('Bild');
  if not(Attr is TRakBinaryPicture) or Attr.IsNull then
    Bild.Graphic := nil
  else
    Bild.Graphic := TRakBinaryPicture(Attr).Graphic;
end;

Das Laden der Daten ist ähnlich einfach, wie das Speichern.

FVorname := Tag.AttributeAsString('Vorname', '');

Den Vornamen hatten wir in einem Attribut mit dem Namen ‚Vorname‘ als String gespeichert.
Deswegen lesen wir den Wert jetzt mit der Methode AttributeAsString aus. Diese Methode erwartet den Namen des Attributes und den Wert, den sie zurückgeben soll, wenn es das Attribut nicht geben sollte, bzw. wenn das Attribut gar keinen String enthält.
In die Methode AttributeAsString schauen wir einmal kurz rein.

function TRakBinaryTag.AttributeAsString(Name: ShortString;
  DefaultValue: AnsiString): AnsiString;
var
  Attr: TRakBinaryAttribute;
begin
  Result := DefaultValue;

  Attr := AttributeByName(Name);
  if Attr <> nil then
  begin
    if Attr is TRakBinaryAnsiString then
      Result := TRakBinaryAnsiString(Attr).Value
    else if Attr is TRakBinaryWideString then
      Result := TRakBinaryWideString(Attr).Value
    else if Attr is TRakBinaryShortString then
      Result := TRakBinaryShortString(Attr).Value;
  end;
end;

Hier können wir sehen, dass nur Attribute vom Typ TRakBinaryAnsiString, TRakBinaryWideString und TRakBinaryShortString akzeptiert werden. Dessen Wert wird dann als AnsiString zurück gegeben. Bei einem TRakBinaryWideString kann es dabei zu Datenverlusten führen, deshalb ist diese Methode im Zusammenhang mit WideStrings mit Vorsicht zu genießen.
Aber wieder zurück zu unserem Code.

FPrivat := Tag.AttributeAsBoolean('Privat', true);

Für das Auslesen von boolean stellt die Klasse TRakBinaryTag auch eine eigene Methode zur Verfügung.
Für TDateTime gibt es keine eigene Methode. Deshalb müssen wir hier etwas mehr Code schreiben.

Attr := Tag.AttributeByName('Geburtstag');
  FGeburtstagNichtVersorgt := not(Attr is TRakBinaryDateTime) or Attr.IsNull;
  if not FGeburtstagNichtVersorgt then
    FGeburtstag := TRakBinaryDateTime(Attr).Value;

Zuerst wird das Attribut angefordert, das die Daten des Geburtstages enthält.
Dann setzen wir unser Flag, ob überhaupt der Geburtstag bekannt ist.
Hierfür gibt es zwei Überprüfungen. Das Attribut muss den richtigen Typ haben. Sollte Attr gleich nil sein, dann ist Attr is TRakBinaryDateTime gleich false. Man muss also keine Angst haben, dass hier eine Exception geworfen wird.
Als zweites wird noch geprüft, ob das Attribut nicht den Null-Wert enthält. Ein Null-Wert müsste jedem bekannt sein, der mit relationalen Datenbanken arbeitet. Der Null-Wert gibt an, dass die entsprechende Information nicht bekannt ist.
Wir haben es beim Speichern so gemacht, dass das Geburtsdatum überhaupt nicht abgespeichert wurde, wenn es nicht bekannt ist. Deshalb dürfte bei uns nie der Null-Wert gesetzt sein. Eine zukünftige Version unseres Kontaktverwalters könnte aber mit dem Null-Wert arbeiten. Deshalb überprüfen wir diesen hier.
Nur wenn das Geburtsdatum bekannt ist, dürfen wir es auch auslesen.
Die Postleitzahl wird genauso gehandhabt wie das Datum. Deshalb gehen wir hier nicht weiter darauf ein. Uns interessiert erst wieder das Laden des Bildes.

Attr := Tag.AttributeByName('Bild');
  if not(Attr is TRakBinaryPicture) or Attr.IsNull then
    Bild.Graphic := nil
  else
    Bild.Graphic := TRakBinaryPicture(Attr).Graphic;

Zuerst wird das Attribut angefordert, welches das Bild enthält.
Wenn das Attribut nicht den erwarteten Typ hat oder leer ist, dann gibt es kein Bild zum Anzeigen.
Andernfalls wird eine Kopie vom Bild des Attributes verwendet.
Die Zuweisung

Bild.Graphic := TRakBinaryPicture(Attr).Graphic;

übernimmt nicht das Graphicobjekt, sondern erstellt eine Kopie.
So, damit sind wir in der Lage die gespeicherten Daten auch wieder auszulesen.
Im nächsten Kapitel sehen wir, dass man die Klassen von RakBinaryStreamData nicht nur für das Speichern in einer Datei, sondern auch für den Austausch über die Zwischablage verwenden kann.