Die Anwendungs-Datenstruktur enthält oft redundante Daten, die nicht unbedingt in einer Datei gespeichert werden müssen, sondern zur Laufzeit aus den gespeicherten Daten berechnet werden können. Zudem will man vielleicht Daten verschlüsselt oder sonst wie codiert in der Datei speichern. Daher ist die zu erzeugende Seq-Struktur nicht unbedingt eine 1:1 Abbildung der Anwendungs-Datenstruktur.
Unter OOP-Richtlinien programmiert man so, dass jedes Anwendungs-Objekt Funktionen bekommt, die sich selbst Serialisieren und Parsen können.
Unsere Anwendung soll eine Liste von Benutzern mit Benutzername, Passwort und Benutzertyp verwalten und ein paar globale Einstellungen speichern können. Die entsprechenden Objekte der Anwendung seien folgendermassen definiert:
class CAppli public Globals ' as CGlobals public UserList ' as CUserList : end class class CGlobals public Language ' as string public LastDate ' as date : end class class CUserList public Users ' as array of CUser : end class class CUser public Name ' as string public Pwd ' as string public IsAdmin ' as boolean : end class
Jede Klasse erhält nun je eine Funktion Serialize, welche aus dem Objekt einen Seq-String erzeugt, und eine Funktion Parse mit der umgekehrten Funktionalität.
Diese Funktionen sind für die Klassen CGlobals und CUser sehr einfach zu implementieren:
class CGlobals : sub Serialize( aSerializer ) aSerializer.OpenSubData 3 aSerializer.AddNL aSerializer.AddStr Language aSerializer.AddDate LastDate aSerializer.CloseSubData end sub sub Parse( aParser ) aParser.OpenSubData Language = aParser.GetStrD( "de" ) LastDate = aParser.GetDateD( Now ) aParser.CloseSubData end sub : end class class CUser : sub Serialize( aSerializer ) aSerializer.OpenSubData 4 aSerializer.AddNL aSerializer.AddStr Name aSerializer.AddStr Pwd aSerializer.AddBool IsAdmin aSerializer.CloseSubData end sub sub Parse( aParser ) aParser.OpenSubData Name = aParser.GetStr() Pwd = aParser.GetStr() IsAdmin = aParser.GetBool() aParser.CloseSubData end sub : end class
Beachte, dass die Properties der Objekte in der gleichen Reihenfolge gelesen werden (GetXxx) wie sie serialisiert wurden (AddXxx)!
Die Funktion AddNL kann zum Formatieren des Seq-String verwendet werden. Sie fügt einen Zeilenumbruch ein, der beim Lesen ignoriert wird, aber das Lesen eines Seq-Files für Menschen erleichtert.
Für die User-Liste sieht Serialize folgendermassen aus:
class CUserList : sub Serialize( aSerializer ) dim sz, i sz = UBound(UserList) + 1 aSerializer.OpenSubData 2 + sz aSerializer.AddNL aSerializer.AddNum sz for i = 0 to UBound(UserList) UserList(i).Serialize( aSerializer ) next aSerializer.CloseSubData end sub sub Parse( aParser ) dim last, user, i UserList = Array() aParser.OpenSubData last = aParser.GetNum() - 1 if last < 0 then aParser.CloseSubData exit sub end if redim UserList( last ) for i = 0 to last set user = new CUser user.Parse aParser set UserList(i) = user next aParser.CloseSubData end sub : end class
Jetzt fehlen nur noch die Funktionen auf Appli-Ebene:
class CAppli : sub Serialize( aSerializer ) aSerializer.OpenSubData 4 aSerializer.AddNL aSerializer.AddStr "CAppli" Globals.Serialize aSerializer UserList.Serialize aSerializer aSerializer.CloseSubData end sub function Parse( aParser ) aParser.OpenSubData if aParser.GetStr() <> "CAppli" then aParser.CloseSubData Parse = false exit function end if Globals.Parse aParser UserList.Parse aParser aParser.CloseSubData Parse = true end function : end class
Der String "CAppli" wird als ID für diese Anwendung gespeichert. Beim Parsen wird der Seq-String überprüft, ob er "CAppli" enthält. Nur dann werden die weiteren Daten eingelesen.
Jetzt fehlen nur noch die Funktionen CAppli.SaveToFile und CAppli.LoadFromFile:
class CAppli : sub SaveToFile( aFilename ) dim serializer, seqString set serializer = NewSerializer(1) Serialize serializer seqString = serializer.GetString(false) FS.WriteFile aFilename, seqString end sub function LoadFromFile( aFilename ) dim seqString, parser LoadFromFile = false seqString = FS.ReadFile( aFilename ) if seqString = "" then exit function set parser = NewParser( seqString ) LoadFromFile = Parse( parser ) end function : end class
Damit können die Appli-Daten sehr einfach in eine Datei gespeichert und wieder geladen werden:
dim Appli set Appli = new CAppli Appli.LoadFromFile "applidata.txt" : Appli.SaveToFile "applidata.txt"
Eine solche Datei applidata.txt könnte folgendermassen aussehen:
72| 6|CAppli|22| 2|de|31.12.2009 23:59|| 38| 2|19| 5|Admin|4|****|1||18| 4|Gast|4|****|0||||