2017-12-31 70 views
0

私はオブジェクトをシリアライズするためにバイナリフォーマッタを使用しています。 シリアル化されたバイト配列のプロパティの順番は何ですか(オブジェクトクラスのプロパティの順序によると思いますか?) そして、もし私が小道具に従ってバイトの順序を制御できるのであれば。例えばC#BinaryFormatter bytes orde

私は、次のOBJシリアライズした場合、
:私はそれをシリアル化する場合は

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

を、バイト手段の順序は何ですか? (最初の4バイトは年齢を表し、次はウェイトですか?など、バイナリフォーマッタはランダムに設定します)

+5

'BinaryFormatter'を使ってデータをシリアライズする場合は、データをデシリアライズするために使用する必要があります。したがって、バイトオーダは問題になりません。 'BinaryFormatter'はあなたのためにすべてを世話します。 'BinaryFormatter'以外のものでデータを扱うことが予想される場合は、それ以外のものを使ってデータを直列化する必要があります。例えば。 'BinaryWriter'は、リトルエンディアンを使用します。率直に言って、あなたが何を求めているのかは本当に明確ではありません。質問は文字通り取ることができますが、実際にはより広い問題を念頭に置いているようです。 –

+2

バイトオーダー(エンディアン)について主に質問しているようですが、_values_の順番も尋ねているようです。 'BinaryFormatter'の出力を解釈する必要がある場合は、どのように解釈しようとしているのかを示す[mcve]、何かが間違っている場合の説明、具体的な内容あなたが知りたいと思っていることを実証しています。 –

+0

私は、ありがとう! – DBS

答えて

4

なぜそれを試してみませんか?あなたのクラス

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

を取り、それをシリアル化することができますし、これは与える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 . 

。ちょっと覗き見たらアセンブリ名、クラス名、フィールド名(kind of)を認識し、jdwengが提供するマジックを適用すると、42(Age)になる4バイト2A 00 00 00と次の4バイトが-1重量)。

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

とのは、変更されたバイト数を見てみましょう:

はのは、最初のフィールドなどの公共分野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 . 

意味をなさないようです。

[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の出力が実装の詳細であり、シリアライズとデシリアライズがそのクラスに残され、他の手段では試みられないことを確信させるものです。

[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;}} 
} 

そして、我々は、そのクラスを初期化する場合は、次のように:

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の順序:

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

をhexdumpに対してはこれを表示します[]配列は最後に置かれます。

だからあなたの質問に答えるために:

を私はシリアル化されたバイト配列内のプロパティの順序が何であるかを知っていただきたいと思い

(?ランダムにオブジェクトクラスのプロパティの順序に従って?)

これは、クラスのフィールドのタイプとその順序に依存する実装の詳細です。それはメタデータであり、実際の値は異なる順序である可能性があります。それはランダムではなく、クラス内での順序ではありません。

そして、私が小道具に従ってバイトの順序を制御できるかどうか。

これはある程度までは制御できるように思われるかもしれませんが、これは実装の詳細の多くであり、影響を与えたり、予測したり、頼ったりするのは現実的ではありません。

クラスの特定のバージョンのみをシリアル化および逆シリアル化できることに注意してください。下位互換性はありません。

シリアル化形式を厳密に制御する必要がある場合は、XML、JSON、proto-bufなどのオープン標準を使用します。または、Peterが提案したBinaryWriterを利用して、独自のシリアライザを起動します。

+0

ありがとう! – DBS

関連する問題