2016-09-19 10 views
0

メンバとは異なる値を持つオブジェクト/クラスをすべてシリアライズできます。オブジェクトをバイトに変換できます。 これらのオブジェクトのリストを1つの大きなバイト配列に変換していましたが、どうすれば元に戻すことができますか?C#オブジェクトの配列にオブジェクトのバイト配列を変換します。

例オブジェクト:

using System; 
using System.IO; 

[Serializable] 
public class MyItem { 
    internal string m_name = ""; 
    internal int m_position = 0; 
    internal float m_color = 0f; 
    internal int m_direction = 0; 
    internal float m_power = 0f; 

    public MyItem(string name, int position, float color, int direction, float power) { 
     m_name = name; 
     m_position = position; 
     m_color = color; 
     m_direction = direction; 
     m_power = power; 
    } 

    public byte[] Serialize() { 
     using (MemoryStream m = new MemoryStream()) { 
      using (BinaryWriter writer = new BinaryWriter(m)) { 
       writer.Write(m_name); 
       writer.Write(m_position); 
       writer.Write(m_color); 
       writer.Write(m_direction); 
       writer.Write(m_power); 
      } 
      return m.ToArray(); 
     } 
    } 

    public static MyItem Desserialize(byte[] data) { 
     string name; 
     int position; 
     float color; 
     int direction; 
     float power; 

     using (MemoryStream m = new MemoryStream(data)) { 
      using (BinaryReader reader = new BinaryReader(m)) { 
       name = reader.ReadString(); 
       position = reader.ReadInt32(); 
       color = reader.ReadSingle(); 
       direction = reader.ReadInt32(); 
       power = reader.ReadSingle(); 
      } 
     } 

     return new MyItem(name, position, color, direction, power); 
    } 
} 

そしてバイト配列に変換する:

List<MyItem> itemlist = <...>; 
List<byte[]> byteList = new List<byte[]>(); 
for (int i = 0; i < itemlist.Count; i++) { 
    byteList.Add(itemlist[i].Serialize()); 
} 
byte[] data = byteList.SelectMany(bytes => bytes).ToArray(); 

バックの変換:

???????? 
+0

集約配列を直列化オブジェクトのサイズのチャンクに分割して逆シリアル化する必要があります。 – itsme86

+0

アイテム間にマーカーを入れないので、単一アイテムのバイトサイズを計算し、データをそのサイズのチャンクに分割し、各チャンクを別々に処理する必要があります。 – kiziu

+0

オブジェクトの配列を直接シリアル化する必要があります。次に、配列全体を直列化解除することができます。 (NB。これは.NET全体のシリアル化への切り替えに基づいています。独自のものではなく、組み込み直列化を使用しているかのように型をマークしています) – Richard

答えて

1

をコメントで述べたように、あなたはバイトを記述する必要がありますストリーム内の各オブジェクトは単一のオブジェクトをデシリアライズできます。例:ここでは

public static class MyItemSerializer 
{ 
    public static byte[] Serialize(this IEnumerable<MyItem> items) 
    { 
     using (MemoryStream m = new MemoryStream()) 
     { 
      using (BinaryWriter writer = new BinaryWriter(m, System.Text.Encoding.UTF8, true)) 
      { 
       foreach (var item in items) 
       { 
        var itemBytes = item.Serialize(); 
        writer.Write(itemBytes.Length); 
        writer.Write(itemBytes); 
       } 

      } 

      return m.ToArray(); 
     } 
    } 

    public static List<MyItem> Deserialize(byte[] data) 
    { 
     var ret = new List<MyItem>(); 
     using (MemoryStream m = new MemoryStream(data)) 
     { 
      using (BinaryReader reader = new BinaryReader(m, System.Text.Encoding.UTF8)) 
      { 
       while (m.Position < m.Length) 
       { 
        var itemLength = reader.ReadInt32(); 
        var itemBytes = reader.ReadBytes(itemLength); 
        var item = MyItem.Desserialize(itemBytes); 
        ret.Add(item); 
       } 
      } 
     } 

     return ret; 
    } 
} 

あなたがアクションでそれを見ることができます:https://dotnetfiddle.net/Nk2cks

をしかし、.NETが既にGoogleでBinaryFormatter

Protobufと呼ばれるシリアライザが含まれていますが、別の可能性です。

+0

なぜBinaryWriterを開いたままにしますか? –

+0

'BinaryWriter'が' MemoryStream'を閉じると、後でいくつかの関数が無効になります。しかし、['ToArray()'](http://stackoverflow.com/questions/3981253/is-calling-memorystream-toarray-dangerous-after-disposing)はまだ有効です。だから、あなたがそれを閉じるなら、それは大丈夫です、私の間違い。 – Nico

関連する問題