Gibt es eine richtige Möglichkeit, ein Dateiformat zu erstellen?

12

Ich erstelle ein proprietäres Dateiformat für eine Anwendung, die ich in C # .NET geschrieben habe, um gespeicherte Informationen und möglicherweise Projektressourcen zu speichern. Gibt es einen Standard, wie dies in irgendeiner Weise zu tun ist? Ich ging einfach zu Serializemeinen Objekten in die Binärdatei und erstellte einen Header, der mir sagte, wie ich die Datei analysieren sollte. Ist das ein schlechter Ansatz?

corylulu
quelle
2
Ich würde es vermeiden BinaryFormatter.
CodesInChaos
3
Welchen Ansatz Sie auch wählen (aus den Antworten), geben Sie immer eine Versionsnummer im Format an! Ihre Frage deutet bereits darauf hin, dass sie sich ändern könnte, und die Versionsnummer erspart Ihnen eine Menge Aufwand, wenn Sie backwarsd-kompatibel sein müssen.
Jan Doggen
Vergessen Sie nicht, das Format richtig zu dokumentieren
Basile Starynkevitch

Antworten:

11

Am einfachsten ist es wahrscheinlich, Ihre Struktur mithilfe der XMLSerializerKlasse in XML zu serialisieren . Sie müssten wahrscheinlich keine separate Header- und Body-Struktur erstellen, sondern alle Assets in XML serialisieren. Auf diese Weise können Sie Ihre Dateistruktur problemlos außerhalb Ihres eigenen Programms überprüfen / bearbeiten und sind einfach zu verwalten.

Wenn Ihre Dateistruktur jedoch sehr komplex ist und viele verschiedene Assets unterschiedlichen Typs enthält, sodass die Serialisierung der gesamten Struktur in XML zu aufwändig ist, sollten Sie die einzelnen Assets separat serialisieren und mithilfe der PackagingBibliothek in C # zu einem einzigen Paket kompilieren. . Auf diese Weise werden im Wesentlichen DOCX-, XSLX-, PPTX- und andere Office-Dateiformate erstellt.

pswg
quelle
Ja, mein Projekt ist viel komplexer als nur das, aber ich versuche auch, es weniger benutzerlesbar zu machen, da wir diese möglicherweise in einem Feld in einem lizenzierten Kontext bereitstellen. Ich verwende derzeit, protobuf-netum meine Daten zu serialisieren und das funktioniert großartig. Aber ich muss Stücke separat serialisieren, damit das, worüber Sie mit der Verpackungsbibliothek sprechen, genau das ist, was ich brauche.
Corylulu
7
Lieber Gott, nicht XML
James
2
@James yeah XML hat natürlich auch seine Schattenseiten. In den meisten Fällen bevorzuge ich Verpackung und XML aus den gleichen Gründen: 1. Es ist ein bereits vorhandenes Framework und erfordert daher nur geringen Aufwand. 2. Es ist für andere Systeme einfach zu unterstützen, da es sich um einen allgemein akzeptierten Standard handelt. 3. Ein Mensch kann die resultierende Datei leicht untersuchen, um den Serialisierungsprozess zu überprüfen.
Pswg
XML hat Vorteile, aber aufgrund dieser Vorteile mag ich den XML-Serializer nicht. Ich glaube, es erfordert die XML in einem bestimmten Format. XML ist ein semi-strukturiertes Format, mit dem sich mein Dateiformat im Laufe der Zeit ändern kann und das dennoch rückwärts- und sogar vorwärtskompatibel ist. In der Vergangenheit habe ich mein eigenes XML-Parsing geschrieben, wobei ich darauf geachtet habe, keine Annahmen über die Bestellung zu machen oder dass es keine Tags gibt, die mir in Zukunft unbekannt sind. Wenn Sie die gesamte XML-Datei laden können, funktioniert XPATH wahrscheinlich recht gut. Ansonsten sind Sie mit etwas komplizierterem Stream-Parsing links
Alan am
Ich würde vorschlagen , Blick in JSON
Basile Starynkevitch
7

Von jemandem, der viele Dateiformate analysieren musste, habe ich eine andere Meinung als die meisten anderen.

  • Machen Sie die magische Zahl sehr einzigartig, damit die Dateiformaterkenner anderer Formate sie nicht als Ihre identifizieren. Wenn Sie Binär verwenden, weisen Sie der magischen Zahl am Anfang eines Binärformats 8 oder 16 zufällig generierte Bytes zu. Wenn Sie XML verwenden, weisen Sie einen geeigneten Namespace in Ihrer Domain zu, damit er nicht mit anderen Personen in Konflikt gerät. Wenn Sie JSON verwenden, hilft Ihnen Gott. Vielleicht hat jemand schon eine Lösung für diesen Gräuel eines Formats gefunden.

  • Planen Sie die Abwärtskompatibilität. Speichern Sie die Versionsnummer des Formats so, dass spätere Versionen Ihrer Software mit Unterschieden umgehen können.

  • Wenn die Datei groß sein kann oder Teile davon vorhanden sind, die aus irgendeinem Grund übersprungen werden sollen, stellen Sie sicher, dass es eine gute Möglichkeit gibt, dies zu tun. XML, JSON und die meisten anderen Textformate sind dafür besonders schrecklich, da sie den Leser zwingen, alle Daten zwischen dem Start- und dem Endelement zu analysieren, auch wenn sie sich nicht darum kümmern. EBML ist etwas besser, da es die Länge der Elemente speichert, sodass Sie bis zum Ende überspringen können. Wenn Sie ein benutzerdefiniertes Binärformat erstellen, gibt es ein weit verbreitetes Design, in dem Sie als Erstes eine Blockkennung und eine Länge in der Kopfzeile speichern. Anschließend kann der Leser den gesamten Block überspringen.

  • Speichern Sie alle Zeichenfolgen in UTF-8.

  • Wenn Sie Wert auf langfristige Erweiterbarkeit legen, speichern Sie alle Ganzzahlen in einer Form mit variabler Länge.

  • Prüfsummen sind nett, weil sie es dem Leser ermöglichen, ungültige Daten sofort abzubrechen, anstatt möglicherweise in Abschnitte der Datei zu gelangen, die zu verwirrenden Ergebnissen führen können.

Trejkaz
quelle
+1, um mir klar zu machen, dass ich nicht die einzige Person bin, die denkt, JSON sei ein Gräuel für ein Format.
RubberDuck
Warum der Hass auf Json? Platzieren Sie einfach eine bekannte Zeichenfolge an einer bekannten Stelle, um das Format zu identifizieren. Problem gelöst.
Esben Skov Pedersen
Es ist nicht perfekt, funktioniert aber nahtlos mit Javascript, ist schneller zu analysieren als XML und kleiner und dennoch für den Menschen lesbar.
Corylulu
1
"Warum der Hass auf JSON?" Keine Unterstützung für von Menschen lesbare Kommentare, das Entkommen von Unicode und eine seltsame Syntax, die mich dazu zwingt, die Schlüssel in Anführungszeichen zu setzen, obwohl sie niemals Leerzeichen enthalten. Und die übliche Unfähigkeit, Dinge zu erweitern, weil sich niemand Gedanken über den Namensraum gemacht hat. Wenn Sie diesen auflösen, erhalten Sie etwas, das noch schlimmer aussieht als XML Klammern?
Trejkaz
Ja, aber wie bei allem, was mit Programmierung zu tun hat, verwenden Sie das richtige Werkzeug für den Job. Es gibt Anwendungen, in denen XML besser ist als JSON und umgekehrt.
Corylulu
4

Nun, es gibt Zeiten, in denen das, was Sie beschreiben, ein sehr schlechter Ansatz sein kann. Dies wird vorausgesetzt, wenn Sie "serialisieren" sagen, dass Sie die Fähigkeit einer Sprache / eines Frameworks verwenden, ein Objekt einfach zu nehmen und direkt in eine Art Binärstrom auszugeben. Das Problem ist, dass sich die Klassenstrukturen im Laufe der Jahre ändern. Können Sie eine in einer früheren Version Ihrer App erstellte Datei erneut laden, wenn sich alle Ihre Klassen in einer neueren ändern?

Um die Langzeitstabilität eines Dateiformats zu gewährleisten, ist es besser, jetzt die Ärmel hochzukrempeln und Ihre eigenen Serialisierungs- / Streaming-Methoden innerhalb Ihrer Klassen zu schreiben. dh manuelles Schreiben von Werten in einen Stream. Schreiben Sie eine Kopfzeile, während Sie angeben, dass die Formatversion beschrieben wird, und speichern Sie dann die Daten in der gewünschten Reihenfolge. Auf der Leseseite wird der Umgang mit verschiedenen Versionen des Dateiformats viel einfacher.

Die andere Option ist natürlich XML oder JSON. Nicht unbedingt die beste für binäre, schwere Inhalte, aber einfach und für den Menschen lesbar ... ein großes Plus für die langfristige Lebensfähigkeit.

GroßmeisterB
quelle
Ich serialisiere mit protobuf-net ( code.google.com/p/protobuf-net ), das erweiterbar ist. Aber Ihre Punkte sind gültig, aber ich glaube nicht, dass es sich um eine Methode handelt, die dagegen immun ist.
Corylulu
Ja ... deshalb muss man sich manchmal die Hände schmutzig machen und die Reihenfolge, in der die Daten manuell geschrieben und geladen werden, regeln.
GroßmeisterB
Die Anwendung, die ich erstelle, ist viel zu dynamisch und hat viel zu viele Werte für so etwas.
corylulu
1
Je komplizierter die Anwendung ist, desto wichtiger ist eine sehr genaue Kontrolle über das Dateiformat. Denken Sie daran, ich sage nicht, dass jede Klasse nicht ihre eigene streambare Ausgabe haben sollte ... nur, dass Sie dies für jede Klasse steuern sollten. Rufen Sie dann einfach diese Routinen auf.
GroßmeisterB
Ja, ich habe Methoden, mit denen ältere Versionen auf moderne Versionen aktualisiert werden können, und ich habe ein sehr klares Layout, wie meine Klassen angeordnet sind. Darüber mache ich mir keine allzu großen Sorgen, aber ich stimme zu, dass es wichtig ist. Ich arbeite seit fast einem Jahr daran, daher habe ich eine ziemlich klare Vorstellung davon, wie die Struktur funktioniert.
Corylulu
1

Ich würde auch gerne Antworten auf diese Frage von Leuten hören, die mehr Erfahrung als ich haben.

Ich habe persönlich mehrere Dateiformate für meine Arbeit implementiert und bin zu einem XML-Dateiformat übergegangen. Meine Anforderungen und die Hardware, mit der ich interagiere, ändern sich ständig, und es ist nicht abzusehen, was ich dem Format in Zukunft hinzufügen muss. Einer der Hauptvorteile von XML besteht darin, dass es halbstrukturiert ist . Aus diesem Grund vermeide ich im Allgemeinen die automatische XML-Serialisierung, die .NET bereitstellt, da ich der Meinung bin, dass ein genaues Format erwartet wird.

Mein Ziel war es, ein XML-Format zu erstellen, mit dem in Zukunft neue Elemente und Attribute hinzugefügt werden können und die Reihenfolge der Tags nach Möglichkeit keine Rolle spielt. Wenn Sie sicher sind, dass Sie Ihre gesamte Datei in den Speicher laden können, ist XPATH wahrscheinlich eine gute Wahl.

Wenn Sie es mit besonders großen Dateien zu tun haben oder die Datei aus anderen Gründen nicht auf einmal laden können, müssen Sie wahrscheinlich einen XmlStreamReader verwenden, um nach bekannten Elementen zu suchen und diese Elemente mit ReadSubtree erneut zu durchsuchen und erneut zu scannen ...

Alan
quelle
Diese Antwort ist nicht sehr an das Q gerichtet, diese Seite ist nicht als Diskussionsforum gedacht, sondern eher für nicht spekulative Fragen und Antworten. Sie haben in Ihrer Antwort einige gültige Punkte gemacht, die verwendet werden könnten, um einen Vorschlag zu argumentieren, warum der Ansatz des Fragenden gut ist oder nicht, aber er ist nicht sehr fokussiert. Bitte konzentrieren Sie Ihre Antwort ein wenig mehr auf die Frage, danke!
Jimmy Hoffa
@JimmyHoffa Obwohl meine Antwort auch die Frage des OP unterstützte, machte ich klar, dass ich einen halbstrukturierten XML-Ansatz vorschlug. Aber ich verstehe, was Sie meinen, ich kann ihn bearbeiten
Alan