【问题标题】:Versioning friendly, extendible binary file format版本控制友好、可扩展的二进制文件格式
【发布时间】:2010-03-29 20:33:11
【问题描述】:

在我目前正在进行的项目中,需要将相当大的数据结构保存到磁盘(编辑:想想几十 MB)。作为一个乐观主义者,我认为这样的问题必须有一个标准的解决方案;但是,到目前为止,我还没有找到满足以下要求的解决方案:

  1. .NET 2.0 支持,最好使用 FOSS 实现
  2. 版本友好(这应该解释为:如果底层数据结构的变化很简单,比如添加/删除字段,读取旧版本的格式应该相对简单)
  3. 能够进行某种形式的随机访问,其中可以在初始创建后扩展部分数据,而无需反序列化到目前为止创建的集合(将其视为扩展中间结果)
  4. 节省空间和时间(鉴于此要求,XML 已被排除在选项之外)

目前考虑的选项:

非常感谢任何建议或指示。此外,如果您认为上述任何信息不正确,请提供指针/示例以证明我错了。

【问题讨论】:

  • HDF5 确实有一些 .NET 支持:hdfgroup.org/projects/hdf.net
  • @Richard Morgan 到目前为止,我只在 hdfgroup.org 上找到了关于 .NET 的死链接,谢谢。
  • 查看了 hdf.net 提供的示例,.net 的想法是使用不安全和自定义编组,没有乐趣。
  • 是的,我应该强调一些

标签: .net binary file-format


【解决方案1】:

您是否考虑过使用SQL Server Compact Edition

  1. 它有大量的 .NET 支持
  2. 架构的版本控制以及新版本应用程序处理旧架构的能力将完全由您控制。除了您的应用程序使用旧版本中不存在的新版本中的功能之外,SQL Server Compact 的版本控制应该有点无缝。
  3. 您拥有可用于查询的大部分 SQL 语法。
  4. 显然,从名称来看,此版本的 SQL Server 是为嵌入式系统设计的,其中可能包含希望避免安装 SQL Express 或 SQL Server 完整版本的应用程序。

现在,这将与 SQLite 存在相同的问题,因为根据您的说法,数据结构可能会变得复杂,但即使您采用自己的二进制格式也是如此。

顺便说一句,我突然想到您还没有澄清“相当大”的确切含义。如果“相当大”意味着接近或超过 4 GB,显然 SQL Compact 将无法工作,许多其他数据库文件格式也不会。

编辑 我注意到您在我的帖子之后已将 SQL Compact Edition 添加到您的“重量级”列表中。 SQL Compact 仅需要 5MB 的 RAM 和 2MB 的磁盘存储,具体取决于数据库的大小。所以,问题不可能是重量级的。现在,关于声称数据结构的第二点将非常复杂。如果这是真的,我怀疑任何关系数据库产品都会如此,并且滚动您自己的二进制格式将更加复杂。鉴于此,您可能会查看非关系型数据库产品,例如 mongodb

【讨论】:

  • 我确实认为 SQL CE 或 SQLite 是最好的方法。在不了解当前数据结构的情况下很难提出建议,但嵌入式数据库确实可以满足所有要求。您还可以使用允许您直接在文件中查询表/数据的工具(以便于调试/测试)。
  • 我同意这个。如果您想要对持久数据进行有效的随机访问,那么您需要一个数据库,可能是关系数据库或 kvp。这正是数据库适合的用途。这是事实上的标准,似乎满足了所有 4 个要求 - 而 SQL CE/SQLite 远非“重量级”。
【解决方案2】:

您会考虑 (B)JSON 吗?如果是这样,面向文档的数据库之一可能适合您的需求。 CouchDB 是一个带有 REST API 的 JSON 文档存储(绝对可以从 .Net 中使用)。 CouchDB 文档可以有二进制附件,我已经与在文档中存储多 MB 附件没有问题的人交谈过。我相信MongoDB,一个使用二进制 JSON 作为存储格式的替代文档数据库,也有 .Net 绑定。​​

这些“NoSQL”替代方案很容易进行版本控制,因为它们本质上是无模式的。 JSON 非常紧凑,它们肯定允许更新现有数据。

【讨论】:

  • 请注意,BSON 被列为废弃选项之一,而且我不希望存储二进制 blob,但 .net 数据结构可能非常大,但由许多部分组成。跨度>
  • BJSON 是磁盘格式的实现细节。对于这种用途,它非常有效。您当然可以轻松地扩展或更新 MongoDB 中的文档,否定您对要求 3 的排除。您可以将数据结构序列化为可以查询的 MongoDB 文档等。磁盘上的任何存储都是磁盘上的二进制 BLOB。这种或任何存储方案都是一种逻辑抽象,可以更轻松地使用磁盘存储。我认为您找不到比文档数据库更好的东西了。
  • 我认为像 mongo 这样的基于文档的 nosql db 可以很好地满足要求 + 如果需要,您可以获得可扩展性选项作为奖励。
【解决方案3】:

您是否考虑过类似db4o 的内容?许可可能会限制您,但它似乎符合要求。

【讨论】:

    【解决方案4】:

    这里有一个有趣的选择:来自 Cisco 的 ETCH,在 Apache 许可下可用(您无需支付版税,您的软件仍然是商业的并且属于您的。)

    这个想法是使用 Etch 以二进制形式在系统的组件之间进行通信。该格式对版本更改具有弹性,并且可以根据您的需求状态处理缺失的字段等。

    好处是您在二进制格式之上获得了更完整的传输系统。它被认为非常快(一台机器每秒执行 900 个 SOAP XML 事务,进行 50,000 个 ETCH 事务)。

    如果您需要多个索引,您可以将二进制化形式存储在轻量级 RDBMS 中。如果只有一个索引就足够了,那么一个简单的键/值存储(CouchDB/MongoDB 甚至分布式环境的 Cassandra)也会为您提供出色的存储性能!

    【讨论】:

      【解决方案5】:

      如果 XML 由于空间消耗而无法满足要求,您可以通过 System.IO.Compression.DeflateStream 提供 XML 以减小其大小。 Deflate 算法本质上与 GZip 压缩相同,但速度最高可提高 40%(请参阅 Jeff Atwood's blog)。

      【讨论】:

      • XML 不可搜索(无索引),压缩流/文件也不可搜索。
      【解决方案6】:

      我不会这么快就注销协议缓冲区。当然,您引用的手册条目说的是兆字节的数量级,而您处理的是数十兆字节……但是您是否尝试过一项研究,看看这种限制是否会影响您?

      如果它仍然对您有影响,我的建议是采用混合方法:将您的数据集切成 1 MB 大小的块,然后将每个块存储为 SQLite 表的一个字段(作为二进制 blob) .为您要索引(或搜索)的元素向表中添加其他字段。

      是的,它增加了复杂性,但似乎没有其他东西可以让您靠近您需要去的地方。

      【讨论】:

        【解决方案7】:

        你看过二进制序列化吗?

        查看我的帖子here 了解更多信息。它具有用于序列化 Dictionary 对象中包含的自定义类的示例代码。不确定您的结构有多复杂,但它应该很容易适应您的需求。

        如果您需要更多帮助,请添加评论...

        【讨论】:

        • 查看我的最新编辑我知道二进制/xml-序列化,但两个选项都被拒绝了。
        • 好的,但是二进制序列化!= xml 序列化。我还是会去看看。
        猜你喜欢
        • 2016-05-06
        • 1970-01-01
        • 1970-01-01
        • 2011-06-28
        • 1970-01-01
        • 1970-01-01
        • 2013-03-20
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多