C#BinaryFormatter字节序 [英] C# BinaryFormatter bytes orde

查看:109
本文介绍了C#BinaryFormatter字节序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用二进制格式化程序来序列化我的对象。
我想知道序列化字节数组中属性的顺序是什么(根据对象类中的属性顺序?随机吗?)
如果我可以根据以下内容控制字节的顺序,

I am using binary formatter in order to serialize my object. I would like to know what is the order of the properties in the serialized byte array (according to properties order in the object class? randomaly?) And if I can control the order of the bytes according to the props.

例如,

如果我序列化以下obj:

For example,
If I serialize the following obj:

public class Human
{
     int Age {get;set;}
     int Weight {get; set;}
}

如果我要对其进行序列化,字节顺序是什么意思? (前4个字节代表年龄,下一个是权重吗?依此类推。还是二进制格式化程序将其随机设置)

If I will serialize it, what is the order of bytes means? (does the first 4 bytes will represent the age, and the next are the weight? and so on.. or the binary formatter set it randomaly)

推荐答案

您为什么不尝试一下呢?让我们参加您的课程

Why don't you just try it? Lets take your class

[Serializable]
public class Human
{
    public int Age {get;set;}
    public int Weight {get; set;}
}

并对其进行序列化,然后通过检查HexDump

And serialize it, then inspect the result by examining the HexDump

var bf = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
using(var ms = new MemoryStream())
{
  bf.Serialize(ms, new Human{ Age = 42, Weight = -1 });
  HexDump(ms.ToArray());
}

这将给出:

00000 : 00 01 00 00 00 FF FF FF FF 01 00 00 00 00 00 00  .....????.......
00016 : 00 0C 02 00 00 00 43 71 75 65 72 79 5F 6C 68 68  ......Cquery_lhh
00032 : 75 78 68 2C 20 56 65 72 73 69 6F 6E 3D 30 2E 30  uxh, Version=0.0
00048 : 2E 30 2E 30 2C 20 43 75 6C 74 75 72 65 3D 6E 65  .0.0, Culture=ne
00064 : 75 74 72 61 6C 2C 20 50 75 62 6C 69 63 4B 65 79  utral, PublicKey
00080 : 54 6F 6B 65 6E 3D 6E 75 6C 6C 05 01 00 00 00 0F  Token=null......
00096 : 55 73 65 72 51 75 65 72 79 2B 48 75 6D 61 6E 02  UserQuery+Human.
00112 : 00 00 00 14 3C 41 67 65 3E 6B 5F 5F 42 61 63 6B  ....<Age>k__Back
00128 : 69 6E 67 46 69 65 6C 64 17 3C 57 65 69 67 68 74  ingField.<Weight
00144 : 3E 6B 5F 5F 42 61 63 6B 69 6E 67 46 69 65 6C 64  >k__BackingField
00160 : 00 00 08 08 02 00 00 00 2A 00 00 00 FF FF FF FF  ........*...????
00176 : 0B  .

这是汉斯所谈论的令人费解的格式。如果您斜视一下,就可以识别一个程序集名称,类名称,字段名称(种类),并且如果使用jdweng提供的魔术,您会注意到4个字节 2A 00 00 00 这将使42(年龄),接下来的4个字节代表-1(体重)。

That is the convoluted format Hans is talking about. If you squint a bit you recognize an assemblyname, the classname, the fieldnames (kind of) and if you apply the magic offered by jdweng you notice the 4 bytes 2A 00 00 00 which would make 42 (Age) and the next 4 bytes represent -1 (Weight).

让我们添加一个公共字段 Name 作为第一个字段:

Let's add a public field Name as the first field:

[Serializable]
public class Human
{
    public string Name;
    public int Age {get;set;}
    public int Weight {get; set;}   
}

,让我们看一下已更改的字节:

and let's look at the changed bytes:

00096 : 55 73 65 72 51 75 65 72 79 2B 48 75 6D 61 6E 03  UserQuery+Human.
00112 : 00 00 00 04 4E 61 6D 65 14 3C 41 67 65 3E 6B 5F  ....Name.<Age>k_
00128 : 5F 42 61 63 6B 69 6E 67 46 69 65 6C 64 17 3C 57  _BackingField.<W
00144 : 65 69 67 68 74 3E 6B 5F 5F 42 61 63 6B 69 6E 67  eight>k__Backing
00160 : 46 69 65 6C 64 01 00 00 08 08 02 00 00 00 06 03  Field...........
00176 : 00 00 00 04 54 65 73 74 2A 00 00 00 FE FF FF FF  ....Test*...????
00192 : 0B  .

这似乎很有意义。让我们将该字段放在末尾:

That seems to make sense. Let's put that field at the end:

[Serializable]
public class Human
{
    public int Age {get;set;}
    public int Weight {get; set;}   
    public string Name;
}

,结果是:

00096 : 55 73 65 72 51 75 65 72 79 2B 48 75 6D 61 6E 03  UserQuery+Human.
00112 : 00 00 00 04 4E 61 6D 65 14 3C 41 67 65 3E 6B 5F  ....Name.<Age>k_
00128 : 5F 42 61 63 6B 69 6E 67 46 69 65 6C 64 17 3C 57  _BackingField.<W
00144 : 65 69 67 68 74 3E 6B 5F 5F 42 61 63 6B 69 6E 67  eight>k__Backing
00160 : 46 69 65 6C 64 01 00 00 08 08 02 00 00 00 06 03  Field...........
00176 : 00 00 00 04 54 65 73 74 2A 00 00 00 FE FF FF FF  ....Test*...????
00192 : 0B  .

完全没有变化。

一个最后一个使您确信BinaryFormatter的输出是实现细节,并且序列化和反序列化应留给该类,而不能通过其他方式尝试。

One final example to convince you that the output of the BinaryFormatter is an implementation detail and that serializing and deserializing should be left to that class and is not be attempted by other means.

[Serializable]
public class Human
{
    public string[] Address; 
    private string _name;

    public int Weight {get; set;} // switched
    public int Age {get;set;}

    public string Name {get{return _name;} set{_name=value;}}
}

如果我们按如下方式初始化该类:

And if we initialize that class as follows:

new Human{ Name ="Test", Age = 42, Weight = -1, Address =new []{"foo","bar"}}

十六进制转储将显示以下内容:

the hexdump will show this:

00096 : 55 73 65 72 51 75 65 72 79 2B 48 75 6D 61 6E 04  UserQuery+Human.
00112 : 00 00 00 07 41 64 64 72 65 73 73 05 5F 6E 61 6D  ....Address._nam
00128 : 65 17 3C 57 65 69 67 68 74 3E 6B 5F 5F 42 61 63  e.<Weight>k__Bac
00144 : 6B 69 6E 67 46 69 65 6C 64 14 3C 41 67 65 3E 6B  kingField.<Age>k
00160 : 5F 5F 42 61 63 6B 69 6E 67 46 69 65 6C 64 06 01  __BackingField..
00176 : 00 00 08 08 02 00 00 00 09 03 00 00 00 06 04 00  ................
00192 : 00 00 04 54 65 73 74 FF FF FF FF 2A 00 00 00 11  ...Test????*....
00208 : 03 00 00 00 02 00 00 00 06 05 00 00 00 03 66 6F  ..............fo
00224 : 6F 06 06 00 00 00 03 62 61 72 0B  o......bar.

请注意地址和_name的顺序,尽管string []数组的实际值位于结束。

Notice the order of Address and _name although the actual values of the string[] array are put at the end.

所以回答您的问题:


我想知道什么是

I would like to know what is the order of the properties in the serialized byte array (according to properties order in the object class? randomly?)

是序列化字节数组中属性的顺序(根据对象类中的属性顺序?是随机的吗?)取决于字段类型及其在类中的顺序的详细信息。元数据和实际值的顺序也可能不同。它不是随机的,也不是类中的顺序。

It is an implementation detail that depends on the type of the field and its order in the class. It's metadata and actual value might be in a different order as well. It is not randomly and it is not the order in the class.


如果我可以根据道具控制字节的顺序

And if I can control the order of the bytes according to the props.

似乎您可以在一定程度上控制它,但这只是实现细节,因此尝试不实际影响,预测或依赖它。

It might seems you can control it to some extent but this is so much of an implementation detail that it is not practical to try to influence it, predict it or rely on it.

请记住,您只能序列化和反序列化该类的特定版本。没有向后兼容性。

Keep in mind that you can only serialize and deserialize the specific version of the class. There is no backward compatibility.

如果您需要严格控制序列化格式,请使用开放标准,例如XML,JSON或原始buf 。或根据Peter的建议利用BinaryWriter滚动自己的序列化器。

If you need to have strict control over the serialization format use an open standard, like XML, JSON or proto-buf. Or roll your own serializer, leveraging the BinaryWriter as suggested by Peter.

这篇关于C#BinaryFormatter字节序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆