在文件的开头写一些您仅在结尾知道的内容


9

背景:我正在编写微控制器C代码来编写EBML文件。EBML就像是带有嵌套元素的二进制XML,但是不是开始和结束标签,而是一个开始ID,长度和数据。我将其写入低功耗应用程序的外部Flash中,因此我希望将Flash的访问量降至最低。内存也很有限,因为没有一件事情容易。

当我可以将整个EBML元素保留在内存中时,生成它很容易,因为在知道长度之后,我可以返回并填写每个元素的长度。问题是当我无法将整个元素保存在内存中时该怎么办。我看到的选项是:

  • 写出我所知道的内容,然后返回并添加长度(最简单,但是添加的闪存访问量比我想要的更多)
  • 在开始编写每个元素之前,先计算它们的长度(相对容易,但是需要很多处理器时间)
  • 一旦我的内存填满,就切换模式,这样我就可以继续浏览数据,但是仅是为了计算已经在内存中保留的元素的长度。然后写出内存中的内容,然后返回并继续从上次中断的地方处理数据。(到目前为止,我最喜欢的选项)
  • 在需要编写元素且最终长度未知时,为它们提供最大或最坏情况的长度。(比上面更容易,但可能适得其反并浪费空间)

问题:看来这应该是人们思考过的相对普遍的问题。我知道在形成一些数据包时也会发生这种情况。我在这里缺少更好/更常见/更容易接受的技术吗?还是我可以搜索的一些术语?


1
/ sccs的工作方式是:完成写入后,它将所有字节的校验和写入文件的开头。在可以自动执行所需文件操作的Unix上运行良好(例如Solaris),并在无法做到这一点的Unix上引起奇怪的零星问题,例如Linux
咬到了

Answers:


2

如果您不知道您的有效载荷将要持续多久,即使您不记得位置并稍后回填长度,也几乎不必担心:

只需记下“未知大小”即可。

该功能取决于由EBML元素组成的有效负载,而以下元素虽然不是有效的子元素。

如果需要,以后可以根据需要以任何方便的方式离线标准化生成的EBML,例如“无大小,最小大小”或“最小大小,避免未知大小”。


有关详细信息,请参阅matroska.org上的EBML RFC草案


这很棒!我没有意识到这一点,它避免了核心问题,但是我仍然希望获得有关解决核心问题的好方法的指导。使用大小未知的元素似乎可能会限制将来的兼容性,因为旧软件可能会在新元素上过早退出。
pscheidler,2017年

您需要正确的DTD,否则就无法真正解码EBML。好吧,如果所有未知元素的大小都可以忽略,那么就足够了吗?只需对要离线存储的任何EBML进行后处理。
Deduplicator

我们正在使用我们自己的架构,该架构将会扩展。在设计时已了解到,较旧的软件最终可能不得不跳过某些数据。但这是我不知道的EBML的一个重要功能,因此我接受了答案。
pscheidler '17

0

如果单个元素具有固定数量的子元素太大,那么也许您应该尝试将其划分为模式。我不知道这种格式,但是很可能您可以在其中定义最大长度。

对于序列,您可以尝试定义下一个文件中剩余的子元素和“流”的最大数量

对于可能超出最大内存大小的元素,请准备一个包含对的堆栈:保留的元素长度位置和长度计数器。在弹出窗口中,将当前计数器保存在当前标记中,然后将其值添加到下一个计数器中。

通常,尝试最小化太大元素的数量


好吧,他可能可以针对自己的EBML元素执行此操作,但这仍然对他的父元素没有帮助。
Deduplicator

您的想法会奏效,但我宁愿创建一个可以处理大型元素的系统,而不是限制架构以避免使用大型元素。
pscheidler,2017年

该解决方案也适用于大型元素,请小心堆栈大小。如果涉及到架构,则将其视为您的应用程序使用的一种语言,如果一个应用程序无法处理复杂的语言,则另一个应用程序应该进行调整,或者需要翻译器。许多开发人员(至少我知道是C / C ++的开发人员)倾向于避免模式/设计更改,就像火灾一样,后来导致系统性能下降。如果其他组件无法调整,则可能分解/设计不佳。如果还有其他原因没有更改,那么您可能应该考虑使用其他硬件
Whoot

0

吻和亚尼
选择选项#1,如果它成为一个真正的问题-请仅重申一下。

至少对于具有类似二进制格式的类似用例,当只需要以这种方式填写几个值时,这是最简单/最简单/最佳的解决方案。如果必须对每个数据块都执行此操作,那么这可能是体系结构中的缺陷。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.