Écrire au début d'un fichier quelque chose que vous ne savez qu'à la fin

9

Contexte: J'écris du code C de micro contrôleur pour écrire un fichier EBML. EBML est comme un XML binaire avec des éléments imbriqués, mais au lieu des balises de début et de fin, il y a un ID de début, une longueur, puis les données. J'écris ceci dans un flash externe dans une application à faible puissance, donc je voudrais garder les accès au flash au minimum. La mémoire est également limitée, car rien n'est jamais facile.

Quand je peux garder la totalité de l'élément EBML en mémoire, il est facile de le générer car je peux revenir en arrière et remplir la longueur de chaque élément une fois que je sais quelle est cette longueur. Le problème est de savoir quoi faire quand je ne peux pas garder l'élément entier en mémoire. Les options que je vois sont:

  • Écrivez ce que je sais, puis revenez en arrière et ajoutez les longueurs (le plus simple, mais ajoute plus d'accès flash que je ne le souhaite)
  • Calculez la longueur de chaque élément avant de commencer à l'écrire (relativement facile, mais beaucoup de temps processeur)
  • Changez de mode une fois que ma mémoire se remplit, pour que je continue ensuite à parcourir les données, mais uniquement pour calculer les longueurs des éléments déjà réservés en mémoire. Ensuite, écrivez ce que j'ai en mémoire et revenez en arrière et continuez à traiter les données là où je les avais laissées. (Mon option préférée jusqu'à présent)
  • Donnez aux éléments une longueur maximale ou la pire des cas lorsqu'ils doivent être écrits et que leur longueur finale n'est pas encore connue. (Plus facile que ci-dessus, mais pourrait se retourner contre vous et gaspiller de l'espace)

Question: Il semble que cela devrait être un problème relativement courant auquel les gens ont pensé. Je sais que cela peut également se produire lors de la formation de certains paquets de données. Y a-t-il une technique meilleure / plus courante / plus acceptée qui me manque ici? Ou juste quelques termes pour le problème que je peux rechercher?

pscheidler
la source
1
/ sccs fonctionne de cette façon: il écrit la somme de contrôle de tous les octets au début du fichier une fois l'écriture terminée. Fonctionne très bien sur Unix qui peut effectuer atomiquement les opérations de fichiers nécessaires (par exemple Solaris) et provoque des problèmes sporadiques étranges sur Unix qui ne peuvent pas le faire, par exemple Linux
gnat

Réponses:

2

Si vous ne savez pas combien de temps durera votre charge utile, cela vous inquiète rarement même si vous ne vous souvenez plus de la position et ne remblayez pas la longueur plus tard:

Notez simplement "taille inconnue".

Cette fonctionnalité dépend de la charge utile constituée des éléments EBML et l'élément suivant n'est cependant pas un élément enfant valide.

Si vous le souhaitez, vous pouvez ultérieurement canoniser l'EBML résultant hors ligne à votre convenance comme vous le souhaitez, par exemple pour "pas de tailles inconnues, taille minimale" ou "taille minimale, éviter les tailles inconnues".


Reportez-vous au projet EBML RFC sur matroska.org pour plus de détails.

Déduplicateur
la source
C'est bien! C'est quelque chose que je n'étais pas au courant et qui évite le problème principal, mais j'aimerais quand même avoir des conseils sur une bonne façon de résoudre le problème principal. L'utilisation d'un élément de taille inconnue semble limiter la compatibilité future, car les anciens logiciels quitteraient prématurément les nouveaux éléments.
pscheidler
Vous avez besoin de la bonne DTD ou vous ne pouvez pas vraiment décoder l'EBML. Eh bien, si tous les éléments inconnus sont dimensionnés, vous pouvez les ignorer, mais est-ce suffisant? Il suffit de post-traiter tout EBML que vous souhaitez stocker hors ligne s'il l'est.
Déduplicateur
Nous utilisons notre propre schéma, qui se développera. Il a été conçu en sachant que les logiciels plus anciens pourraient éventuellement devoir ignorer certaines données. Mais c'est une grande fonctionnalité d'EBML que je n'étais pas au courant, donc j'accepte la réponse.
pscheidler
0

Si un seul élément avec un nombre fixe de sous-éléments est trop grand, alors vous devriez peut-être essayer de le diviser en schéma. Je ne connais pas ce format, mais vous pouvez très probablement y définir une longueur maximale.

Pour les séquences, vous pouvez essayer de définir le nombre maximal de sous-éléments et le "flux" restant dans le fichier suivant

Pour les éléments dépassant potentiellement la taille maximale de la mémoire, préparez une pile contenant des paires: emplacement de longueur d'élément réservé et compteur de longueur. À la pop, enregistrez le compteur actuel dans le marqueur actuel et ajoutez sa valeur au compteur suivant.

En général, essayez de minimiser le nombre d'éléments trop gros

Whoot
la source
Eh bien, il pourrait probablement le faire pour ses propres éléments EBML, mais cela ne l'aide toujours pas avec l'élément parent.
Déduplicateur
Votre idée fonctionnerait, mais je préfère créer un système capable de gérer de gros éléments, au lieu de contraindre le schéma de manière à éviter les gros éléments.
pscheidler
Cette solution fonctionnera également pour les grands éléments, mais faites attention à la taille de la pile. Et s'il s'agit de schéma ... pensez-y comme un langage que vos applications utilisent, si l'un ne peut pas gérer un complexe, alors l'autre doit s'ajuster ou un traducteur est requis. De nombreux développeurs (du moins ceux que je connais en C / C ++) ont tendance à éviter les modifications de schéma / conception comme s'il s'agissait d'un incendie, ce qui entraîne plus tard un système médiocre. Si un autre composant ne peut pas s'ajuster, il est peut-être mal décomposé / conçu. S'il y a d'autres raisons de ne pas changer, alors vous devriez probablement envisager l'utilisation d'un matériel différent
Whoot
0

KISS et YAGNI.
Choisissez l'option # 1 et si cela devient un vrai problème - réitérez-la ensuite.

Au moins pour des cas d'utilisation similaires avec des formats binaires similaires, lorsque seulement quelques valeurs devaient être remplies de cette manière, c'est la solution la plus simple / la plus facile / la meilleure. Si vous devez le faire sur chaque morceau de données - cela pourrait être une faille dans l'architecture.

Kromster
la source