ISerializable 对象应该如何存储二进制数据?

Posted

技术标签:

【中文标题】ISerializable 对象应该如何存储二进制数据?【英文标题】:How should ISerializable object store binary data? 【发布时间】:2013-11-30 08:17:21 【问题描述】:

我有一个引用类型,它在非托管内存中包含原始图像数据。很清楚如何使用SerializationInfo 存储元数据(宽度、高度),但是存储 BLOB 的最佳方式是什么?

我唯一能看到的是使用Convert.ToBase64String,这需要大量的复制。有没有更直接的方法?

【问题讨论】:

【参考方案1】:

更新:有更好的方法来处理这个问题!

您需要做的是查看传递给GetObjectDataStreamingContextStreamingContext.State 属性可以告诉您正在发生什么样的序列化。如果您通过了CloneCrossAppDomain 状态,您可能能够重用您对非托管blob 拥有的现有句柄,只需将句柄指针传递给SerializationInfo 对象。


无论您选择什么,您都需要进行大量复制,但Convert.ToBase64String 是不必要的,您只需将您传递给Convert.ToBase64String 的托管byte[] 序列化就可以了。


我不知道byte[] 是否有任何特殊情况的效率,但是在传输过程中所有序列化get turned in to a byte stream。因此,通过在 Base64 中编码,您将要做的事情

    读取非托管 blob 并将其转换为托管 byte[] 通过ToBase64String 将您的byte[] 转换为string(由于编码,大小增加了4/3 倍)李> 将带有标签名称的编码字符串传递给SerializationInfo 将其余元数据及其相应标签传递到SerializationInfo 序列化程序获取所有标签+对象组合并将它们转换为字节流以传递到目标 反序列化器获取字节流并将其转回标签和对象的集合 您使用相同的标签名称返回您的string 您可以使用保存元数据的标签取回元数据。 通过FromBase64Stringstring 转换回byte[]byte[] 转换回非托管二进制 blob。

如果您从不编码为字符串,而只是将 byte[] 作为对象传递给 SerializationInfo 对象,则步骤几乎相同,只是没有那个 4/ 3 增加数据块的大小以将二进制数据编码为文本。

    读取非托管 blob 并将其转换为托管 byte[] 将带有标签名称的byte[] 传递给SerializationInfo 将其余元数据及其相应标签传递到SerializationInfo 序列化程序获取所有标签+对象组合并将它们转换为字节流以传递到目标 反序列化器获取字节流并将其转回标签和对象的集合 您使用相同的标签名称返回您的byte[] 您可以使用保存元数据的标签取回元数据。 将 byte[] 转换回非托管二进制 blob。

所以我猜想“优化”是作为byte[] 传输的,其好处是不会增加您必须传输到去耳化器的数据量。

【讨论】:

这很不幸。 byte[] 是为了提高效率而特例,你知道吗,还是将元数据存储在每个单独的元素后面作为单独的项目?有没有其他简单的方法可以在程序运行之间存储一些对象? 我添加了一个广泛的更新来回答您问题的第一部分。对于您的第二个问题,这取决于您的目标是什么:最简单的实现、最小的大小、人类可读、跨平台支持、跨 .NET 框架版本支持? (如果最后一个答案是“否”,那么BinaryFormmater 可能是“最简单”的解决方案)? @BenVoigt 我之前没想过,是的,任何传入AddValue( 的this overload 的对象可以进行优化.将会发生的事情是它将在传入的对象上调用GetObjectData(),并且嵌套的searlizer会执行它选择做的任何优化(因此由Array的seralizer来确定是否有任何优化) 您还应该考虑的一件事,如果您序列化为byte[],然后将您的序列化流传递给XMLSearalizer,它会将byte[] 文件编码为十六进制,这将在大小上比 Base64 编码效率低得多,所以也许 Base64 会更好。 这就是我所怀疑的。虽然我担心它可能会更糟,例如逗号分隔的十进制编码值列表。

以上是关于ISerializable 对象应该如何存储二进制数据?的主要内容,如果未能解决你的问题,请参考以下文章

Serializable 指示一个类可以序列化;ICloneable支持克隆,即用与现有实例相同的值创建类的新实例(接口);ISerializable允许对象控制其自己的序列化和反序列化过程(接口)(

如何在二进制堆中存储任何类型的可比较对象

如果内容需要与 iCloud 同步,我应该如何存储图像

将 ISerializable 与 DataContractSerializer 一起使用时,如何阻止序列化程序输出类型信息?

编写高质量代码改善C#程序的157个建议——建议57:实现ISerializable的子类型应负责父类的序列化

ISerializable 接口的意义何在?