【问题标题】:BinaryFormatter bytes usageBinaryFormatter 字节使用情况
【发布时间】:2021-07-21 10:59:07
【问题描述】:

我在玩 BinaryFormatter 并开始序列化。 用于序列化大型事物,如列表、数组等,并且没有考虑使用的字节,因为我知道有一些魔术字节、类型定义、数据值以及其他我无法想象的东西。 F.e:

int[] values = new int[5]{1,2,3,4,5};

结果为 48 字节长。 然后发生了一些事情,让我陷入了困境,我序列化了一个 int,它有 58 个字节长。

    MemoryStream stream = new MemoryStream();
    BinaryFormatter formatter = new BinaryFormatter();
    formatter.Serialize(stream, 5);

我错过了什么吗?导致较大的数据(例如类数组)使用较少的内存。 为什么基本类型需要所有这些字节? 整个 int ( Int32 结构)被序列化了吗?具有 5 个值的 int[] 仍然需要更少的字节。

【问题讨论】:

  • 看起来BinaryFormatter 有一种比原语本身更紧凑的方式来序列化原语数组。比较:dotnetfiddle.net/b1vVUR。看看它需要如何将原语序列化为其完全限定名称及其成员的名称,而数组则获得更紧凑的编码。永远不要期望BinaryFormatter 生成您类型的 compat 二进制表示:它不是为此而设计的。事实上,不要使用它,因为它不可能确保安全,并且已被弃用
  • 作为关于使用 BinaryFormatter 的一般评论,众所周知,它是脆弱、不安全、缓慢且效率低下的。还有更好的替代品,比如 Protobuf、json、bson 等。
  • c# 有隐藏类型和部分结构。所以你的数组有 5 个整数(30 个字节)加上 28 个字节的开销,其中包括变量类型。

标签: c# serialization


【解决方案1】:

如果你为你得到的数组对 MemoryStream 进行十六进制转储:

array 
00000 : 00 01 00 00 00 FF FF FF FF 01 00 00 00 00 00 00  .....????.......
00016 : 00 0F 01 00 00 00 05 00 00 00 08 01 00 00 00 02  ................
00032 : 00 00 00 03 00 00 00 04 00 00 00 05 00 00 00 0B  ................

对于你得到的 int 值:

value 
00000 : 00 01 00 00 00 FF FF FF FF 01 00 00 00 00 00 00  .....????.......
00016 : 00 04 01 00 00 00 0C 53 79 73 74 65 6D 2E 49 6E  .......System.In
00032 : 74 33 32 01 00 00 00 07 6D 5F 76 61 6C 75 65 00  t32.....m_value.
00048 : 08 05 00 00 00 0B                                ......

位置 0x17 处的字节很可能是“接下来会发生什么”指示符,因为在很长一段时间内该字节仍然是 04。

我不必解释有什么区别。对于数组,有一个针对已知类型的优化序列化方案。对于其他任何内容,序列化程序包括类型名和内部实现细节(在本例中为m_value),这可能是该类型的实际值支持字段。

正如 JonasH 在 their comment 中所指出的那样,类似于我之前写的答案 C# BinaryFormatter bytes orde 不要对 BinaryFormatter 的作用有太多疑问,最重要的是不要依赖其行为在框架的各个版本中保持稳定甚至是你的程序集的版本(如果你以这种格式序列化你自己的类型)并且稳定我的意思是:能够在以后反序列化你今天序列化的内容。

【讨论】:

    猜你喜欢
    • 2018-06-11
    • 1970-01-01
    • 1970-01-01
    • 2019-07-19
    • 2023-03-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多