反序列化一个struct数组

时间:2012-06-26 08:11:18

标签: c# arrays struct deserialization

我再一次通过UDP从C ++程序接收结构, 现在我将结构移植到C#,例如:

[Serializable]
struct sample
{
public int in;
public byte[] arr;
public int[] arr2;
public float fl;
}

好的,那么Deserializer如何知道一个数组何时结束而另一个数组何时开始呢? 可以用某种方式指定数组有多大? 我不想使用fixed,因为这会使我的代码不安全,而且我也不能使用构造函数,因为不允许结构包含没有参数的构造函数。

有什么建议吗?

//编辑:

已知数组长度为32和4。 问题是我不知道如何将这些信息传递给反序列化器

然后发件人是C ++就像这样:

char* pr = &sample;
int i=0;
while (i<sizeof(sample))
{
 udp.send(*(pr+i))
 i++;
}

4 个答案:

答案 0 :(得分:2)

既然您告诉我们长度是预先定义的长度,那么以下陈述就会变得更加清晰:

  

我不知道如何将此信息传递给反序列化程序

事实上,它变得 moot 。没有预定义的序列化程序可以帮助您。您有两种选择:

答:编写自己的序列化程序,并在知道格式后处理数据 - 可能使用BinaryReader

using(var reader = new BinaryReader(source)) {

    int in = reader.ReadInt32();
    byte[] arr = reader.ReadBytes(32);
    int[] arr2 = new int[4];
    for(int i = 0 ; i < 4 ; i++) arr2[i] = reader.ReadInt32();
    float fl = reader.ReadSingle();

    var obj = /* something involving ^^^ */
}

B:缓冲区56个字节,并使用非常讨厌的unsafe / fixed /指针敲击代码

我强烈建议第一个。特别是,如果需要,这还允许您处理字节顺序。

以你所做的一切为名,不要这样做:

using System;
using System.Runtime.InteropServices;
[StructLayout(LayoutKind.Explicit)]
unsafe struct sample
{
    [FieldOffset(0)] public int @in;
    [FieldOffset(4)] public fixed byte arr[32];
    [FieldOffset(36)] public fixed int arr2[4];
    [FieldOffset(52)] public float fl;    
}

static class Program
{
    unsafe static void Main()
    {
        byte[] buffer = new byte[56];
        new Random().NextBytes(buffer); // some data...

        sample result;
        fixed(byte* tmp = buffer)
        {
            sample* ptr = (sample*) tmp;
            result = ptr[0];
        }

        Console.WriteLine(result.@in);
        Console.WriteLine(result.fl);
    }    
}

对于较大的缓冲区,您可以将ptr视为多个sample的不安全数组,可通过索引访问:

int @in = ptr[i].@in;

(等)

但说实话......有太多东西&#34;邪恶&#34;有了这个,老实说,我不知道从哪里开始......只是......除非你知道绝对那里的每一行都做了什么,之前做过,并了解所有的陷阱...... 不要想到它

答案 1 :(得分:1)

这取决于用于通过网络传递结构的格式。

如果说它是json,那么每个字段都有一个键,数组将被[]包围。

如果说它是xml,那么你会期望一个带有子节点的arr节点。

如果它是某种任意格式,您需要知道格式。

反序列化器有一些默认行为,但如果传递的数据不是默认格式,则需要告诉它们如何反序列化。

答案 2 :(得分:1)

原始数据如何记录?我希望在这里可以告诉你一些事情,例如,我可能希望它说格式是(纯粹是一个例子)

  • 4字节NBO Int32(in
  • 4字节NBO Int32(长度arr
  • len bytes(arr
  • 4字节NBO(长度arr2
  • 4 * len字节(arr2,每个在NBO Int32中)
  • 4字节IEEE-754(fl

您需要知道格式。

编辑:如果C ++数组具有已知的固定长度,那么您只需要提前知道这些长度。

答案 3 :(得分:0)

由于你正在使用[Serializable],我假设你正在使用二进制序列化器。它仅序列化字段并编码足够的额外信息以识别字段,类型等。

所以没有必要在别处指定长度。

我建议使用类而不是结构。