Escribir al principio de un archivo algo que solo sabes al final


9

Antecedentes: estoy escribiendo el código C del microcontrolador para escribir un archivo EBML. EBML es como un XML binario con elementos anidados, pero en lugar de etiquetas de inicio y fin, hay una ID de inicio, longitud y luego los datos. Estoy escribiendo esto en Flash externo en una aplicación de baja potencia, por lo que me gustaría mantener los accesos de flash al mínimo. La memoria también es limitada, porque nada es fácil.

Cuando puedo mantener todo el elemento EBML en la memoria, generarlo es fácil porque puedo regresar y completar la longitud de cada elemento después de saber cuál es esa longitud. El problema es qué hacer cuando no puedo mantener todo el elemento en la memoria. Las opciones que veo son:

  • Escriba lo que sé, luego regrese y agregue las longitudes (lo más fácil, pero agrega más acceso flash de lo que quiero)
  • Calcule la longitud de cada elemento antes de comenzar a escribirlo (relativamente fácil, pero mucho tiempo de procesador)
  • Cambiar de modo una vez que mi memoria se llene, de modo que luego continúe con los datos, pero solo para calcular las longitudes de los elementos ya reservados en la memoria. Luego escriba lo que tengo en la memoria, regrese y continúe procesando los datos desde donde los dejé. (Mi opción favorita hasta ahora)
  • Otorgue a los elementos la longitud máxima o peor de los casos cuando necesitan ser escritos y su longitud final aún no se conoce. (Más fácil que el anterior, pero podría ser contraproducente y desperdiciar espacio)

Pregunta: Parece que este debería ser un problema relativamente común en el que la gente haya pensado. Sé que también puede suceder cuando se forman algunos paquetes de datos. ¿Hay una técnica mejor / más común / más aceptada que me falta aquí? ¿O solo algunos términos para el problema que puedo buscar?


1
/ sccs funciona de esta manera: escribe la suma de comprobación de todos los bytes al comienzo del archivo después de que haya terminado de escribir. Funciona muy bien en Unixes que pueden realizar operaciones de archivos necesarias atómicamente (por ejemplo, Solaris) y causa problemas esporádicos extraños en Unixes que no pueden hacer eso, por ejemplo, Linux
gnat

Respuestas:


2

Si no sabe cuánto durará su carga útil, rara vez es motivo de preocupación, incluso si no puede recordar la posición y rellenar la longitud más tarde:

Solo anota "tamaño desconocido".

Sin embargo, esa característica depende de la carga útil que consta de elementos EBML y el siguiente elemento no es un elemento hijo válido.

Si lo desea, puede canonizar el EBML resultante sin conexión a su conveniencia de la manera que desee, por ejemplo, "sin tamaños desconocidos, tamaño mínimo" o "tamaño mínimo, evite tamaños desconocidos".


Consulte el borrador de EBML RFC en matroska.org para obtener más detalles.


¡Esto es genial! Es algo de lo que no estaba al tanto y evita el problema central, pero todavía me gustaría recibir orientación sobre una buena manera de resolver el problema central. El uso de un elemento de tamaño desconocido parece que podría limitar la compatibilidad futura, ya que el software antiguo se cerraría prematuramente en nuevos elementos.
pscheidler

Necesita el DTD correcto o realmente no puede decodificar EBML. Bueno, si todos los elementos desconocidos están dimensionados, puede omitirlos, pero ¿es eso suficiente? Simplemente procese cualquier EBML que desee almacenar sin conexión si es así.
Deduplicador

Estamos utilizando nuestro propio esquema, que se expandirá. Ha sido diseñado con el conocimiento de que el software más antiguo podría eventualmente saltarse algunos datos. Pero esta es una gran característica de EBML que desconocía, así que acepto la respuesta.
pscheidler

0

Si un solo elemento con un número fijo de subelementos es demasiado grande, entonces quizás debería intentar dividirlo en un esquema. No conozco este formato, pero lo más probable es que pueda definir una longitud máxima en él.

Para secuencias, puede intentar definir el recuento máximo de subelementos y la "secuencia" restante en el siguiente archivo

Para elementos que potencialmente excedan el tamaño máximo de memoria, prepare una pila que contenga pares: ubicación de longitud de elemento reservada y contador de longitud. En el pop, guarde el contador actual en el marcador actual y agregue su valor al siguiente contador.

En general, trate de minimizar el número de elementos demasiado grandes.


Bueno, probablemente podría hacerlo por sus propios elementos EBML, pero eso todavía no lo ayuda con el elemento padre.
Deduplicador

Su idea funcionaría, pero preferiría crear un sistema que pueda manejar elementos grandes, en lugar de restringir el esquema para evitar elementos grandes.
pscheidler

Esta solución también funcionará para elementos grandes, solo tenga cuidado con el tamaño de la pila. Y si se trata de un esquema ... piense en él como un lenguaje que usan sus aplicaciones, si uno no puede manejar uno complejo, entonces el otro debe ajustarse o se requiere un traductor. Muchos desarrolladores (al menos C / C ++ que conozco) tienden a evitar cambios en el esquema / diseño como si fuera un incendio, lo que luego resulta en un sistema deficiente. Si otro componente no puede ajustarse, entonces quizás esté mal descompuesto / diseñado. Si hay otras razones para no cambiar, entonces probablemente debería considerar el uso de un hardware diferente
Whoot

0

BESO Y YAGNI.
Elija la opción n. ° 1 y, si se convierte en un problema real, solo repítalo.

Al menos para casos de uso similares con formatos binarios similares, cuando solo se tenían que rellenar un par de valores de esta manera, esta es la solución más simple / más fácil / mejor. Si tiene que hacer esto en todos y cada uno de los datos, entonces podría ser un defecto en la arquitectura.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.