【问题标题】:deserialize data on the fly from stream or file从流或文件中动态反序列化数据
【发布时间】:2016-08-05 09:46:25
【问题描述】:

使用 boost::serialize 等常用库序列化和反序列化数据结构或多或少相当容易。

但也有一种常见的情况,我只需执行类似(伪代码)之类的操作:

// receiver
NetworkInputStreamSerialzer stream;

while (1) // read new data objects from stream
{
    stream & data;
}

正如我所料,数据包必须已经从网络套接字完整接收。如果只能读取对象的一部分,则反序列化将失败。特别是对于大型数据集,TCP 会将数据分片。

有没有通用的方法来处理这个问题?我在 boost::serialize 的文档中没有找到任何关于这个问题的提示。

由于这个问题对于任何类型的流数据都是通用的,不仅对于基于 TCP 的流,而且对于一个 prog 发送和另一个接收数据的文件,必须有一个通用的解决方案,但我找不到任何关于。

我的问题不是专门用来提升的。我仅将其用作示例。

编辑: 也许对我的“碎片化”措辞有更多解释:

任何类型的数据,无论其以序列化格式生成的大小如何,都可以在通过 TCP 传输或将其写入任何类型的文件时分成多个包。操作系统不支持任何“原子”读写操作,我所知道的序列化库也不支持。

因此,如果从 XML 或 JSON 等人类可读格式读取 int,我可能会遇到问题,如果“2”不在流或文件中,我会读取“11”而不是“112”。从中读取。因此以人类可读的格式编写以下内容的长度也不是一个解决方案,因为在内容字符串此时不完整的那一刻发生读取时,大小信息本身可能会损坏。

【问题讨论】:

  • 为什么不把你的大数据单元拆分成可以单独处理的小数据单元呢?
  • @SanderDeDycker:如果生成大量小数据集,也会出现碎片化。它应该可以正常工作。
  • 问题是要知道——在反序列化你的大数据单元时——你何时可以使用一些反序列化的数据,特别是哪些反序列化的数据可用。相反,如果您将数据单元拆分为可以单独反序列化的较小数据单元,则您确切知道数据何时可用(在一个小数据单元被完全接收和反序列化之后),以及哪些数据可用(与该小数据单元相关的数据)数据单元)。我不确定你所说的碎片是什么意思。您将以相同的顺序发送相同的数据,只是进行明确的拆分。
  • @SanderDeDycker 我试图澄清一下我的问题。见更新。 if instead you split up the data unit into smaller data units 将无济于事,因为没有保证以原子方式传输的大小。好的,拆分为单个字节会有所帮助:-)

标签: c++ serialization


【解决方案1】:

[注意:我从您的 Q 中了解到,对于您的具体情况,您希望为boost::serialization 提供更好的替代方案。如果这不能回答您的问题,请告诉我,我将删除它。]

根据自己的实践经验推荐使用Google Protocol Buffers。以下是一些优点:

  1. 可用于有线(TCP 等)
  2. 编写 .proto 文件的简单语法,用于编写您自己的文件 消息
  3. 跨平台并支持多种语言
  4. 与 JSON 和 XML 相比非常高效
  5. 为方便的 getter、setter、序列化生成头文件和源文件, 反序列化和调试目的
  6. 易于序列化和反序列化 -- 存储到文件并从文件中检索

最后一点有点棘手。存储在文件中时,您可能必须先插入消息的长度,而在检索时,您可能必须先读取该长度,然后使用read() 方法读取确切的字节数。

在 TCP 上传递时,您可能希望使用上述相同的技巧。在前几个字节中,可以传递长度。一旦确定了长度,就可以随时收集剩余的碎片消息。

【讨论】:

  • "你可能必须先插入消息的长度,然后在检索时," 问:是否保证总是可以从文件中完整(原子)读取长度信息?也许正是这些信息被写入文件的块边界并且数据变得可用,同时可以读取磁盘中的第一个块,但大小信息的最后一个字节存储在下一个块中?
  • @Klaus,我不确定文件长度信息的原子性。在所有实际场景中,它都运行良好。但是,这是一个很好的观点。
猜你喜欢
  • 2014-05-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-04-18
  • 1970-01-01
相关资源
最近更新 更多