Random Access, Persistenz und ein Schichtenmodell

Dateien, Sequenzen und wahlfreier Zugriff auf abstrakte Datentypen.

Jeder Programmierer wird früher oder später mit dem Thema Dateizugriff konfrontiert. Dieser Artikel soll zeigen, dass Dateien mehr sind als nur Datenpersistenz. Anhand des von Niklaus Wirth in den 80er Jahren aufgestellten Schichtenmodells stecken hinter jedem Datenzugriff abstrakte Datentypen und eine abstrakte Denkweise die hilfreich ist, wiederkehrende Vorgänge zweckmäßg einzuordnen. Ganz wesentlich ist die Prägung des Dateibegriffes nach Niklaus Wirth:

  1. Dateien sind Bytesequenzen,
  2. Sequenzen werden sequentiell gelesen,
  3. Sequenzen werden sequentiell geschrieben,
  4. Wahlfreier Zugriff (Random Access) findet nicht auf Dateiebene statt,
  5. Random Access findet nicht in Sequenzen statt,
  6. Wahlfreier Zugriff wird über den Hauptspeicher (RAM) abgewickelt,
  7. Zwischen einer Sequenz und der darin transportierten Datenstruktur vermittelt ein (Serialize)Algorithmus.

Das Erste was auffällt ist die Gleichsetzung von Sequenz mit Datei. Das heißt, dass nach o.g. Definition eine Datei nicht nur das ist, was physikalisch auf einem Datenträger geschrieben ist. Somit dienen Dateien nicht nur der Datenspeicherung sondern auch dem Transport. Der Serialize-Algorithmus und dessen Umkehrung realisiert sozusagen die Verpackung. Alle heute eingesetzten API's für Dateizugriffe und Datentransport implementieren dieses Schichtenmodell weil es sich immer wieder als zweckmäßig erwiesen hat.

Algorithmen, abstrakte Datentypen und Dateitypen

Eng verbunden mit dem Begriff des Content-Type ist der Algorithmus welcher zwischen Sequenz und dem darin transportierten abstrakten Datentyp vermittelt. Während die Sequenz aus Programmsicht lediglich einen einfachen $scalar darstellt, kann ein abstrakter Datentyp wesentlich komplexere Datenstrukturen beinhalten. Das Array ist ein Beispiel für einen einfachen abstrakten Datentyp, der deswegen abstrakt heißt weil es eine bestimmte Vorschrift oder Methode gibt für den wahlfreien Zugriff auf einzelne Arrayelemente -- Den Index.

Content-Type: text/plain; Charset=utf-8 definiert eine Datei als Textdatei. In einer Solchen lassen sich sehr verschiedene abstrakte Datentypen transportieren, beispielsweise ein Array und jede Zeile wäre ein einzelnes Arrayelement. Genausogut könnte ein Algorithmus aber auch festlegen, dass jedes einzelne Wort ein Arrayelement ist. Und mit der Angabe der Zeichenkodierung handelt es sich ebenfalls lediglich um eine Deklaration welche die Datei als Sequenz gar nicht kennt, denn: Auch Textdateien sind nur Bytesequenzen.

Merke: Die Angabe des Content-Type und einer bestimmten Zeichenkodierung ist eine Zusatzinformation die über den Dateibegriff hinausgeht. Diese Information kann in einer Datei bzw. Sequenz enthalten sein, muss aber nicht. Daher ist es beim plattformübergreifenden Transport stets wichtig, Zusatzinformationen auch zusätzlich zu übertragen. Des Weiteren wäre es weit gefehlt, nur anhand des Content-Type auf die in der Sequenz transportierte Datentruktur schließen zu können wie am Beispiel application/json sofort jedem klar wird: Dieser Content-Type sagt allein nichts darüber aus, ob ein einfaches Array oder ein assoziatives Array mit Schlüssel-Werte-Paaren oder gar eine ganze hierarchische Datenstruktur übertragen wird, die ein Serializer rekursiv durchlaufen muss um jedes Element zu erfassen.

Bytesemantic, Charactersemantic und Zeichenkodierung

Bereits beim Entwurf eines Serialize-Algorithmus ist zu überlegen ob dieser zeichenorientiert oder bytesemantisch arbeiten soll. Zeichenorientiert heißt zum Beispiel, dass bestimmte Zeichen und auch Zeilenumbrüche zum Strukturieren verwendet werden, auf diese Art und Weise dient in CSV-Dateien ein Komma als Feld- bzw. Spaltentrenner. Bytesemantisch hingegen heißt, dass ein Serializer mit Offset- und Längenangaben arbeitet. Auch Schablonen, die beispielsweise festlegen dass für jedes Arrayelement in der Sequenz ein bestimmter Offset reserviert ist, arbeiten byteorientiert. In Fakt beziehen sich Offsetangaben in einer Datei grundsätzlich auf die Anzahl an Bytes und keinesfalls auf die Anzahl an Zeichen!

Eben letzter Umstand macht deutlich, dass auf Byteebene die Zeichenkodierung überhaupt noch keine Rolle spielt, Dateien kennen keine Zeichenkodierung, Dateien kennen nur Bytes. Eine bestimmte Zeichenkodierung kommt erst ins Spiel wenn die Frage Byte- oder Charactersemanic entschieden wurde. Dabei ist es unerheblich, ob die Festlegung der Zeichenkodierung unmittelbar am Data Access Layer oder später im Programm getroffen wird.

Literatur

Niklaus Wirth, Algorithmen und Datenstrukturen mit Modula-2, B.G. Teubner Stuttgart 1986


Datenschutzerklärung: Diese Seite dient rein privaten Zwecken. Auf den für diese Domäne installierten Seiten werden grundsätzlich keine personenbezogenen Daten erhoben. Das Loggen der Zugriffe mit Ihrer Remote Adresse erfolgt beim Provider soweit das technisch erforderlich ist. s​os­@rolf­rost.de.