Überlegungen beim Entwerfen eines Dateityps

8

Ich bin dabei, einen Prozess zum Speichern einer Datenstruktur aus Code in eine Datei eines proprietären, noch nicht definierten Typs zu schreiben. Ich habe jedoch noch nie einen Dateityp oder eine Struktur entworfen.

  • Gibt es im Allgemeinen Dinge, die ich berücksichtigen sollte, bevor ich mit dem Entwurf beginne?
  • Gibt es hier akzeptierte bewährte Verfahren? Schlechte Praktiken, die ich vermeiden sollte?
  • Irgendwelche absoluten Do's und Don'ts?
Andy Hunt
quelle
3
Hallo ab 2016! Dies ist die Lehrbuchdefinition einer zu weit gefassten Frage :) Es wäre hilfreich, wenn Sie Einzelheiten zu dem angeben würden, was Sie erreichen möchten. Die meisten proprietären Dateiformate sind für etwas konzipiert . Was sind Ihre Anforderungen?
Andres F.
Vergessen Sie nicht den Hauptvorteil der Verwendung eines Standardformats: Andere Tools und Anwendungen können es einfacher aufnehmen. Und Sie sind möglicherweise nicht die einzige Person, die mit diesen Daten arbeitet. Wenn Sie nach diesem Prinzip arbeiten, ist Ihre Software flexibler, und dies vereinfacht die Dinge.
Joey Adams

Antworten:

20

Versuchen Sie zunächst, ein Format zu finden, das dem zu erstellenden Format nahe genug kommt. Im Allgemeinen ist es besser, das Format einer Person zu verwenden, als das eigene zu erfinden, auch wenn das Format etwas komplexer zu sein scheint als das, was Sie benötigen 1 .

Wenn Sie kein geeignetes vorgefertigtes Format finden, prüfen Sie, ob Sie Ihr eigenes Format auf einem vorhandenen Universalformat wie XML oder Binär-XML aufbauen können . Dies sollte in fast allen Fällen möglich sein, wenn Sie ein neues Dateiformat starten möchten. Textbasiertes XML benötigt mehr Platz, bietet dem Menschen jedoch ein gewisses Maß an Lesbarkeit. Wenn Sie jedoch feststellen, dass Sie die Base-64-Codierung in einer XML-Datei verwenden, ist dies ein klarer Hinweis darauf, dass Sie stattdessen eine binäre Codierung hätten verwenden sollen.

Stellen Sie in Bezug auf gute und schlechte Praktiken sicher, dass Sie die Hardwarefunktion Ihrer ursprünglichen Zielplattform nicht in das Design Ihres Dateiformats "einbinden". Stellen Sie insbesondere sicher, dass Ihre Nummern in einem Format gespeichert sind, das auf Plattformen mit einer anderen Endianness als die des Schreibers korrekt gelesen werden kann , und dass Ihre benutzerbezogenen Zeichenfolgen in UNICODE gespeichert sind.

Eine weitere bewährte Methode besteht darin, einen Header einzuschließen, anhand dessen der Dateityp ermittelt werden kann, falls die Erweiterung fehlt oder falsch ist. Es ist eine gute Idee, eine Version Ihres Dateiformats in den Header aufzunehmen. Auf diese Weise können Sie das Format später ändern und abwärtskompatibel bleiben.

Wenn möglich, machen Sie Ihr Format nicht von den Besonderheiten des in Ihre Plattform integrierten Standard-Serialisierungsmechanismus abhängig. Beispielsweise ergeben binär serialisierte Java-Objekte kein gutes Dateiformat 2 .

Entscheiden Sie abschließend , ob Ihre Dateien streambar sein müssen . Dies führt zu einer zusätzlichen Komplexität, da einzelne "Frames" Ihrer Datei isoliert interpretiert werden sollten. In Fällen, in denen Sie Streamfähigkeit benötigen, sollten Sie jedoch fast immer in der Lage sein, ein geeignetes Dateiformat zu finden, das bereits vorhanden ist.


1 Auf der anderen Seite sollten Sie Formate vermeiden, die außergewöhnliche Anstrengungen erfordern, um die Komplexität zu unterstützen, die Ihre Anwendung erfordert.

2 Dies bedeutet jedoch nicht, dass Sie nicht versuchen sollten, das Lesen und Schreiben Ihres neuen Formats individuell in das Serialisierungsschema Ihrer Plattform zu integrieren, sondern sich nicht auf die Standardmechanismen der Serialisierung verlassen sollten.

dasblinkenlight
quelle
3
Unicode ist kein Format. Es ist nur eine Zuordnung. UTF-8 ist ein Format und wird allgemein als das richtige Format für tragbare Textzeichenfolgen angesehen (es sei denn, Sie verarbeiten CJK-Text. In diesem Fall ist UTF-16LE wahrscheinlich das am zweithäufigsten verwendete Format für Zeichenfolgen)
squarewav
12

Das erste, was Sie berücksichtigen sollten, ist, ob Sie tatsächlich ein neues Format benötigen oder ob Sie ein bereits vorhandenes Format verwenden können. Erwägen Sie die Verwendung von SQLite. Wenn Sie Ihre Anforderungen an das RDBMS-Modell anpassen können, können Sie sich viele Kopfschmerzen ersparen. Erwägen Sie auch die Verwendung von XML oder JSON. Dadurch müssen Sie keinen eigenen Parser schreiben.

Wenn Sie Ihr eigenes Format erstellen müssen, ist die erste Überlegung, ob Sie ein Textformat oder ein Binärformat wünschen. Beides hat Vorteile. Ein Textformat ist ein großer Gewinn für die Portabilität und hat den Vorteil, dass es für einen Menschen einfacher zu lesen oder zu bearbeiten ist. Ein Binärformat könnte effizienter sein, hat jedoch viele Portabilitätsprobleme. Versuchen Sie nicht, Bytes direkt in Variablen einzulesen. Sie werden es bereuen, wenn Sie den Code auf eine andere Plattform portieren müssen.

Dirk Holsopple
quelle
Denken Sie beim Entwerfen Ihres eigenen Formats auch daran, dass Sie beschädigte Dateien berücksichtigen und sicherstellen müssen, dass diese Ihre App nicht beschädigen. Wenn Sie XML verwenden, verwenden Sie bitte aus Liebe zu allem, was Ihnen wichtig ist: VERWENDEN SIE EINEN XML-PARSER. Es spielt keine Rolle, welche (Ihre Sprache bietet möglicherweise eine), aber analysieren Sie XML nicht selbst.
Michael Kohne
SQLite, wenn Sie eine Datenbank mit einzelnen Datensätzen benötigen, die sofort geändert werden können. JSON Wenn es in Ordnung ist, alle Daten in den Speicher zu lesen, ändern Sie sie im Speicher und schreiben Sie sie dann zurück in die Datei.
Gnasher729
1
@ MichaelKohne: Gleiches gilt für JSON. Ich würde schätzen, dass 10% der iOS-Fragen Abstürze betreffen, wenn JSON eine Null enthält, bei der eine Zeichenfolge erwartet wird.
Gnasher729
2

Ihre erste und wichtigste Entscheidung ist, ob Sie ein Binärformat oder ein textbasiertes Format verwenden. Binär ist der richtige Weg, wenn Sie große Mengen auf Nicht-String-Daten ausgeben müssen. Aber es hat erhebliche Nachteile:

  • Binärdaten sind nicht für Menschen lesbar. Dies erschwert das Debuggen und / oder Optimieren von Daten, die sich bereits auf der Festplatte befinden, erheblich. Dies ist einer der Gründe, warum die UNIX-Philosophie textbasierte Dateien so stark umfasst.

  • Binärformate eignen sich nicht für zukünftige Erweiterungen. Während dies möglich ist, müssen Punkte für die Erweiterbarkeit von Anfang an in das Format integriert werden. Typischerweise sind dies

    1. Eine magische Zahl / Zeichenfolge, die das Format identifiziert

    2. eine Formatversionsnummer

    3. reservierte Felder an strategischen Positionen, die auf Null initialisiert werden müssen

    Die ersten beiden werden normalerweise direkt am Anfang der Datei angezeigt, während reservierte Felder normalerweise über die Datei verteilt sind.


Wenn Sie sich für den textbasierten Weg entscheiden, sollten Sie Folgendes beachten:

  • Jedes textbasierte Format definiert eine neue Minisprache. Wisse das und nutze es zu deinem Vorteil.

  • Versuchen Sie, die Regeln Ihrer Minisprache so einfach wie möglich zu halten. Es gibt keinen Ort, an dem das KISS-Prinzip wichtiger ist als beim Entwerfen eines textbasierten Dateiformats.

  • Versuchen Sie, Ihre Dateien selbsterklärend zu machen.

  • Legen Sie keine unnötigen Einschränkungen fest, z. B. wo und wie viel Leerzeichen angezeigt werden.

  • Schauen Sie sich eine Reihe verschiedener Dateiformate an, die für UNIX entwickelt wurden. Dies kann Ihnen einige gute Ideen geben.

  • Wenn möglich, verwenden oder anpassen / erweitern / beschränken Sie ein vorhandenes Dateiformat. Das JSON- Format ist ein gut lesbarer, guter Ausgangspunkt. (Zumindest viel besser als XML, was für Menschen ein Problem beim Lesen ist.)

  • Wenn die Dateigröße ein Problem darstellt, können Sie trotzdem ein textbasiertes Format verwenden, es jedoch über einen der Standardkompressoren wie gzipoder weiterleiten lzma. Die Standardkompressoren lieben solche Eingaben.


Wenn Sie den binären Weg gehen, sollten Sie Folgendes beachten:

  • Sie sollten einen Header mit einer magischen Nummer / Zeichenfolge und einer Versionsnummer haben. Normalerweise geht dies zum Anfang der Datei, aber es kann auch zum Ende der Datei gehen. Einige Dateien haben möglicherweise sogar zwei unterschiedliche Header vorne und hinten, sodass zwei unabhängige Ansichten der darin enthaltenen Daten angezeigt werden.

  • Sie sollten einen Index haben und versuchen, seine Teile nahe beieinander zu halten. Auf diese Weise kann ein Leser schnell herausfinden, was sich in der Datei befindet, ohne das gesamte Objekt scannen zu müssen. Wenn Sie dies nicht tun, lesen Sie möglicherweise alles zweimal.

  • Wenn Sie Bits der Datei haben, auf die nur als Sequenz anstatt über eine Indexstruktur zugegriffen werden kann, fügen Sie jedem Datensatz in der Sequenz mindestens ein Längenfeld hinzu. Für Leser, die nicht alle Details Ihres Formats verstehen und Teile davon als Black Box überspringen müssen, sind entweder ein Index oder Felder mit einer solchen Länge erforderlich. (Danke an Jules für diesen einen.)

  • Jedes Datenobjekt in der Datei muss mindestens ein reserviertes Feld für zukünftige Erweiterungen enthalten. Das muss nicht groß sein, aber es muss da sein. Wenn dies nicht der Fall ist, gibt es keinen Ort, an dem Sie die zukünftigen Funktionen erkennen könnten.

  • Sie müssen Endianess berücksichtigen. In der Regel bedeutet dies, dass Sie einmal entscheiden, ob Ihre Dateien in Big-Endian- oder Little-Endian-Bytereihenfolge codiert werden sollen, und sich an diese Entscheidung halten: Der Umgang mit Endianess wie diesem ist ein Ärgernis, aber bei weitem nicht so schlimm, als müssten Sie zwei verschiedene Versionen berücksichtigen der Endianess in der Datei.

  • Seien Sie großzügig in der Breite der Felder, die Sie bereitstellen. Verwenden Sie insbesondere immer 64 Bit, wenn Sie Offsets in der Datei codieren müssen. Viele Kopfschmerzen wurden von Dateiformat-Designern verursacht, die mit der Anzahl der zugewiesenen Bits zu konservativ waren.

cmaster - Monica wieder einsetzen
quelle
Ich werde eine weitere für Binärdateien hinzufügen: Wenn Sie eine Folge von Datensätzen unterschiedlichen Typs haben (was eine sehr nützliche Struktur ist), gehen Sie NICHT davon aus, dass ein Leser der Datei alle Typen versteht. Verwenden Sie Längenindikatoren, damit unbekannte Datensätze übersprungen werden können.
Jules
@Jules Richtig, du bist :-) Ich habe das als Punkt 3 für die Binärdateien hinzugefügt.
cmaster
0

Es hängt wirklich davon ab, was Sie tun. Es sollte so einfach wie möglich und nicht einfacher sein. Ich sehe viele andere Leute, die XML pushen. Ich rate dringend von der Verwendung von XML ab. XML ist ein überbestimmtes Durcheinander. Die erste Frage wäre, ob Ihre Datenstrukturen Verzweigungen haben. Bedeutet das, dass es sich um Listen von Listen oder Listen von Karten oder dergleichen handelt? Wenn nein, ist eine einfache Folge von Textdatensätzen möglicherweise gut. CSV vielleicht.

Wenn Sie Leistung oder Direktzugriff benötigen, ist Binärdatei gut. Definieren Sie eine Folge von Datensätzen, wobei jeder Datensatz eine Folge von Daten enthält, die eine bestimmte Größe haben, z. B. eine 4-Byte-Little-Endian-Ganzzahl für eine bestimmte Zahl oder eine 2-Byte-Ganzzahl, die die Anzahl der Bytes für eine UTF-8-Zeichenfolge angibt. Lassen Sie jeden Datensatz mit einer Ganzzahl beginnen, die die Größe des Datensatzes angibt, damit die gesamte Datei gescannt werden kann, ohne den Inhalt der Datensätze tatsächlich zu lesen. Auf diese Weise können Sie Datensätze auch vor Ort codieren (dh Sie können die Datei mmap, den Datensatz codieren und anschließend die Größe aktualisieren, um unnötiges Kopieren zu minimieren). Dies ist die Art von Dingen, die Sie mit XML nicht tun können.

squarewav
quelle