Schreiben Sie am Anfang einer Datei etwas, das Sie erst am Ende wissen

9

Hintergrund: Ich schreibe C-Code für Mikrocontroller, um eine EBML-Datei zu schreiben. EBML ist wie ein binäres XML mit verschachtelten Elementen, aber anstelle von Start- und End-Tags gibt es eine Start-ID, eine Länge und dann die Daten. Ich schreibe dies in einer Anwendung mit geringem Stromverbrauch in externes Flash, daher möchte ich die Flash-Zugriffe auf ein Minimum beschränken. Der Speicher ist ebenfalls begrenzt, da nichts jemals einfach ist.

Wenn ich das gesamte EBML-Element im Speicher behalten kann, ist es einfach, es zu generieren, da ich zurückgehen und die Länge jedes Elements eingeben kann, nachdem ich weiß, wie lang es ist. Das Problem ist, was zu tun ist, wenn ich nicht das gesamte Element im Speicher halten kann. Die Optionen, die ich sehe, sind:

  • Schreiben Sie, was ich weiß, und gehen Sie dann zurück und fügen Sie die Längen hinzu (am einfachsten, fügt aber mehr Flash-Zugriff hinzu, als ich möchte).
  • Berechnen Sie die Länge jedes Elements, bevor ich mit dem Schreiben beginne (relativ einfach, aber viel Prozessorzeit).
  • Wechseln Sie den Modus, sobald mein Speicher voll ist, so dass ich dann mit den Daten fortfahre, aber nur, um die Längen für Elemente zu berechnen, die bereits im Speicher reserviert sind. Schreiben Sie dann, was ich im Speicher habe, und gehen Sie zurück und verarbeiten Sie die Daten dort weiter, wo ich aufgehört habe. (Meine bisherige Lieblingsoption)
  • Geben Sie Elementen eine maximale oder Worst-Case-Länge, wenn sie geschrieben werden müssen und ihre endgültige Länge noch nicht bekannt ist. (Einfacher als oben, könnte aber nach hinten losgehen und Platz verschwenden)

Frage: Es scheint, dass dies ein relativ häufiges Thema sein sollte, über das die Leute nachgedacht haben. Ich weiß, dass es auch beim Bilden einiger Datenpakete passieren kann. Gibt es eine bessere / allgemeinere / akzeptiertere Technik, die mir hier fehlt? Oder nur einige Begriffe für das Problem, nach dem ich suchen kann?

pscheidler
quelle
1
/ sccs funktioniert folgendermaßen: Es schreibt die Prüfsumme aller Bytes am Anfang der Datei, nachdem das Schreiben abgeschlossen ist. Funktioniert hervorragend unter Unixen, die benötigte Dateivorgänge atomar ausführen können (z. B. Solaris) und verursacht seltsame sporadische Probleme unter Unixen, die dies nicht können, z. B. Linux
Mücke

Antworten:

2

Wenn Sie nicht wissen, wie lang Ihre Nutzlast sein wird, ist dies selten ein Grund zur Sorge, auch wenn Sie sich nicht an die Position erinnern und die Länge später wieder auffüllen können:

Notieren Sie sich einfach "unbekannte Größe".

Diese Funktion hängt von der Nutzlast ab, die aus EBML-Elementen besteht, und das folgende Element ist jedoch kein gültiges untergeordnetes Element.

Wenn Sie möchten, können Sie die resultierende EBML später nach Belieben offline kanonisieren, z. B. "keine unbekannten Größen, minimale Größe" oder "minimale Größe, unbekannte Größen vermeiden".


Weitere Informationen finden Sie im EBML RFC-Entwurf auf matroska.org.

Deduplikator
quelle
Das ist toll! Es ist etwas, das mir nicht bewusst war und das das Kernproblem vermeidet, aber ich möchte immer noch eine Anleitung zur guten Lösung des Kernproblems. Die Verwendung eines Elements unbekannter Größe scheint die zukünftige Kompatibilität einzuschränken, da alte Software bei neuen Elementen vorzeitig beendet wird.
Pscheidler
Sie benötigen die richtige DTD oder können EBML nicht wirklich dekodieren. Wenn alle unbekannten Elemente die Größe haben, können Sie sie überspringen, aber ist das genug? Verarbeiten Sie einfach alle EBMLs, die Sie offline speichern möchten, wenn dies der Fall ist.
Deduplikator
Wir verwenden unser eigenes Schema, das erweitert wird. Es wurde mit dem Wissen entwickelt, dass ältere Software möglicherweise einige Daten überspringen muss. Aber dies ist eine großartige Funktion von EBML, die mir nicht bekannt war, daher akzeptiere ich die Antwort.
Pscheidler
0

Wenn ein einzelnes Element mit einer festen Anzahl von Unterelementen zu groß ist, sollten Sie möglicherweise versuchen, es in ein Schema zu unterteilen. Ich kenne dieses Format nicht, aber höchstwahrscheinlich können Sie darin eine maximale Länge definieren.

Für Sequenzen können Sie versuchen, die maximale Anzahl von Unterelementen und "Streams" zu definieren, die in der nächsten Datei verbleiben

Bereiten Sie für Elemente, die möglicherweise die maximale Speichergröße überschreiten, einen Stapel mit Paaren vor: Position der reservierten Elementlänge und Längenzähler. Speichern Sie beim Popup den aktuellen Zähler in der aktuellen Markierung und addieren Sie den Wert zum nächsten Zähler.

Versuchen Sie im Allgemeinen, die Anzahl der zu großen Elemente zu minimieren

Whoot
quelle
Nun, er könnte es wahrscheinlich für seine eigenen EBML-Elemente tun, aber das hilft ihm immer noch nicht mit dem übergeordneten Element.
Deduplikator
Ihre Idee würde funktionieren, aber ich würde lieber ein System erstellen, das große Elemente verarbeiten kann, anstatt das Schema so einzuschränken, dass große Elemente vermieden werden.
Pscheidler
Diese Lösung funktioniert auch für große Elemente. Seien Sie nur vorsichtig mit der Stapelgröße. Und wenn es um das Schema geht ... stellen Sie es sich als eine Sprache vor, die Ihre Anwendungen verwenden. Wenn eine nicht mit einer komplexen Sprache umgehen kann, sollte die andere angepasst werden oder ein Übersetzer ist erforderlich. Viele Entwickler (zumindest C / C ++ - Entwickler, die ich kenne) neigen dazu, Schema- / Designänderungen zu vermeiden, als wäre es ein Brand, der später zu einem schlechten System führt. Wenn eine andere Komponente nicht angepasst werden kann, ist sie möglicherweise schlecht zerlegt / konstruiert. Wenn es andere Gründe gibt, sich nicht zu ändern, sollten Sie wahrscheinlich die Verwendung einer anderen Hardware in
Betracht ziehen
0

KISS und YAGNI.
Wählen Sie Option 1 und wiederholen Sie diese, wenn dies zu einem echten Problem wird.

Zumindest für ähnliche Anwendungsfälle mit ähnlichen Binärformaten ist dies die einfachste / einfachste / beste Lösung, wenn nur einige Werte auf diese Weise gefüllt werden mussten. Wenn Sie dies für jeden einzelnen Datenblock tun müssen, liegt möglicherweise ein Architekturfehler vor.

Kromster
quelle