我上周花了很长时间研究序列化.在那段时间里,我发现了很多使用BinaryFormatter或XmlSerializer的例子.不幸的是,我没有找到任何全面详细说明两者之间差异的例子.
我的好奇心的起源在于为什么BinaryFormatter能够直接反序列化到接口而XmlSerializer不能.Jon Skeet在回答" 在运行时转换为多个(未知类型) "时提供了直接二进制序列化到接口的示例.Stan R.在他对" XML Object Deserialization to Interface "的回答中使用XmlSerializer为我提供了实现目标的方法.
除了明显的BinaryFormatter利用二进制序列化,而XmlSerializer使用XML我想更全面地理解基本差异.何时使用其中一种或各自的利弊.
.net c# serialization xml-serialization binary-serialization
我正在使用二进制序列化(BinaryFormatter)作为临时机制,将状态信息存储在一个相对复杂(游戏)对象结构的文件中; 文件比我想象的要大得多,我的数据结构包括递归引用 - 所以我想知道BinaryFormatter是否实际存储了相同对象的多个副本,或者我的基本"对象和值的数量是否应该有"arithmentic是偏离基础的,或者其他地方的过度规模来自于.
搜索堆栈溢出我能够找到Microsoft的二进制远程格式的规范:http://msdn.microsoft.com/en-us/library/cc236844( PROT.10) .aspx
我找不到的是任何现有的查看器,它使您能够"查看"二进制格式化输出文件的内容 - 获取文件中不同对象类型的对象计数和总字节数等;
我觉得这一定是我的"google-fu"让我失望(我什么都没有) - 任何人都可以帮忙吗?这一定是以前做过的,对吧?
更新:我找不到它并且没有得到答案所以我把相对快速的东西放在一起(链接到下面的可下载项目); 我可以确认BinaryFormatter不存储同一对象的多个副本,但它会向流中打印相当多的元数据.如果您需要高效存储,请构建自己的自定义序列化方法.
我正在BinaryFormatter和Protobuf-net序列化器进行一些比较,并对我发现的内容非常满意,但奇怪的是,Protobuf-net设法将对象序列化为比我刚写入值时更小的字节数组.将每个属性转换为没有任何元数据的字节数组.
我知道如果设置AsReference为Protobuf-net支持字符串实习true,但在这种情况下我不是这样做的,那么Protobuf-net默认提供一些压缩吗?
以下是您可以运行以查看的一些代码:
var simpleObject = new SimpleObject
{
Id = 10,
Name = "Yan",
Address = "Planet Earth",
Scores = Enumerable.Range(1, 10).ToList()
};
using (var memStream = new MemoryStream())
{
var binaryWriter = new BinaryWriter(memStream);
// 4 bytes for int
binaryWriter.Write(simpleObject.Id);
// 3 bytes + 1 more for string termination
binaryWriter.Write(simpleObject.Name);
// 12 bytes + 1 more for string termination
binaryWriter.Write(simpleObject.Address);
// 40 bytes for 10 ints
simpleObject.Scores.ForEach(binaryWriter.Write);
// 61 bytes, …Run Code Online (Sandbox Code Playgroud) 我正在使用BinaryFormatterC#中的某些对象进行二进制序列化.但是,某些对象包含我通过DLL访问但没有源代码的类,因此我无法使用该Serializable属性标记它们.是否有一种简单的方法来序列化它们?我有一个解决方法,涉及获取类NoSource和创建一个新类SerializableNoSource,构造函数接受一个NoSource对象,并从中提取我需要的所有信息,但它是hacky.还有更好的选择吗?
当BinaryFormatter反序列化流为对象,似乎没有调用构造函数来创建新的对象.
它是怎么做到的?为什么?.NET中还有其他功能吗?
这是一个演示:
[Serializable]
public class Car
{
public static int constructionCount = 0;
public Car()
{
constructionCount++;
}
}
public class Test
{
public static void Main(string[] args)
{
// Construct a car
Car car1 = new Car();
// Serialize and then deserialize to create a second, identical car
MemoryStream stream = new MemoryStream();
BinaryFormatter formatter = new BinaryFormatter();
formatter.Serialize(stream, car1);
stream.Seek(0, SeekOrigin.Begin);
Car car2 = (Car)formatter.Deserialize(stream);
// Wait, what happened?
Console.WriteLine("Cars constructed: " + Car.constructionCount);
if …Run Code Online (Sandbox Code Playgroud) 我需要避免序列化Event类成员,因为当事件由未标记为Serializable的对象处理时,序列化将失败.
我尝试在Event类成员上使用NonSerialized属性,但无法编译.这行代码:
<NonSerialized()> Public Event PropertyValueChanged()
Run Code Online (Sandbox Code Playgroud)
产生以下错误:
属性'NonSerializedAttribute'不能应用于'PropertyValueChanged',因为该属性在此声明类型上无效.
Public Event PropertyValueChanged() ' compiles but needs the extra handling described below
Run Code Online (Sandbox Code Playgroud)
有没有其他方法可以避免序列化活动成员?
如果事件未被处理,这不是问题,我可以通过在序列化之前克隆对象(并忽略事件)来解决它.只是想知道是否有更好的方法.
谢谢.
当使用 SignalR 和 MessagePack 在 JavaScript 和 C# 之间序列化和反序列化值时,我在接收端看到 C# 中的一些精度损失。
例如,我将值 0.005 从 JavaScript 发送到 C#。当反序列化的值出现在 C# 端时,我得到的值0.004999999888241291很接近,但不是 0.005。JavaScript 端的值是Number和我正在使用的 C# 端double。
我读过 JavaScript 无法准确表示浮点数,这会导致像0.1 + 0.2 == 0.30000000000000004. 我怀疑我看到的问题与 JavaScript 的这个特性有关。
有趣的部分是,我没有看到同样的问题反过来。将 0.005 从 C# 发送到 JavaScript 会导致 JavaScript 中的值 0.005。
编辑:来自 C# 的值只是在 JS 调试器窗口中缩短了。正如@Pete 提到的,它确实扩展到不完全是 0.5 的值(0.005000000000000000104083408558)。这意味着差异至少发生在双方。
JSON 序列化没有相同的问题,因为我假设它通过字符串传递,这使得接收环境处于控制状态,并将值解析为其本机数字类型。
我想知道是否有一种方法可以使用二进制序列化在双方都有匹配的值。
如果不是,这是否意味着无法在 JavaScript 和 C# 之间进行 100% 准确的二进制转换?
使用的技术:
我的代码基于 …
我很困惑 - 我应该何时使用XML序列化,何时应该在.NET框架中使用二进制序列化?
.net c# serialization xml-serialization binary-serialization
我收到一条 protobuf 消息 -
message Sample{
string field1 = 1;
string field2 = 2;
string field3 = 3;
}
Run Code Online (Sandbox Code Playgroud)
这些消息以二进制格式存储在数据存储中。因此,如果我想删除上述消息中的任何定义字段,是否会导致从数据存储区反序列化消息时出现任何问题?
serialization protocol-buffers binary-serialization deserialization protobuf-java
鉴于这样一个类:
[Serializable]
public class MyClass {
string name;
string address;
public MyClass(SerializationInfo info, StreamingContext context){
name = info.GetString("name");
if(/* todo: check if a value for address exists */)
address = info.GetString("address");
}
public void GetObjectData(SerializationInfo info, StreamingContext context){
info.AddValue(name);
if(address != null)
info.AddValue(address);
}
}
Run Code Online (Sandbox Code Playgroud)
如何address在调用之前测试字段的值是否存在info.GetString(address)?
是的,我确实理解我可以简单地写一个空address字段,但我真正的问题是早期版本的MyClass,没有地址字段.
注意:我有充分的理由使用自定义序列化.有一些静态字段被用作单例,默认的反序列化不会尊重它.
c# ×8
.net ×6
binary ×1
constructor ×1
events ×1
javascript ×1
msgpack ×1
protobuf-net ×1
signalr ×1
vb.net ×1