如何将C#Struct转换为字节数组

时间:2015-05-11 12:14:25

标签: c# arrays struct char copy

我有一个结构,我想通过TCP协议发送到TCP客户端,所以我想将这个结构数据分配或复制到字节数组:

struct StartReadXML
   {
       public int CmdID;//3
       public char[] CmdName;//ReadXML
       public char[] Description;//Other data

   };

这里正在为结构数据成员分配数据,如下所示:

StartReadXML startXML=new StartReadXML();
startXML.CmdID = 3;
startXML.CmdName = "sreedhar".ToCharArray();
startXML.Description = "Kumar".ToCharArray();

现在,我希望将它分配给一个字节数组。使用编组如下所示:

int sizestartXML = Marshal.SizeOf(startXML);//Get size of struct data
byte[] startXML_buf = new byte[sizestartXML];//byte array & its size
IntPtr ptr = Marshal.AllocHGlobal(sizestartXML);//pointer to byte array
Marshal.StructureToPtr(startXML, ptr, true);
Marshal.Copy(ptr, startXML_buf, 0, sizestartXML);
Marshal.FreeHGlobal(ptr);

//Sending struct data  packet
stm.Write(startXML_buf, 0, startXML_buf.Length);//Modified

但是,它在Structuretoptr转换方法中失败了。请帮助将结构数据转换为使用上述步骤的字节。     在此先感谢Smile | :) !!

2 个答案:

答案 0 :(得分:2)

您无法在可变大小的数组上调用StructureToPtr

这归结为,除非你知道CmdName的大小并声明它 - 例如,如果它是20个字符大小,如下:

public fixed char[] CmdName[20];

你将受到Marshal的例外表示,你的结构要么不闪现,要么无法获得有意义的大小。

这是CLR强加的要求,您无法解决。

另一种方法是使用Convert类或序列化程序手动转换结构的成员,但除非你事先了解这些数组的大小,否则你将无法使用StructureToPtr - 同样适用于string类型,因为我假设您的字符数组将包含的内容。

考虑使用MemoryStream并将值写入流,然后使用stream.ToArray()发送流的内容。

答案 1 :(得分:0)

考虑到您不能简单地将二进制转换为二进制结构,请使用例如:

class StartReadXML
{
    public int CmdID;//3
    public string CmdName;//ReadXML
    public string Description;//Other data
}

然后:

var srx = new StartReadXML();
srx.CmdID = 3;
srx.CmdName = "sreedhar";
srx.Description = "Kumar";

// Example of how to Write to byte[] buffer

byte[] buffer;

using (var ms = new MemoryStream())
{
    using (var bw = new BinaryWriter(ms, Encoding.UTF8))
    {
        bw.Write(srx.CmdID);
        bw.Write(srx.CmdName);
        bw.Write(srx.Description);
    }

    buffer = ms.ToArray();
}

// Example of how to Read from byte[] buffer

var srx2 = new StartReadXML();

using (var ms = new MemoryStream(buffer))
{
    using (var br = new BinaryReader(ms, Encoding.UTF8))
    {
        srx2.CmdID = br.ReadInt32();
        srx2.CmdName = br.ReadString();
        srx2.Description = br.ReadString();
    }
}

请注意,我在这里使用"可变长度"数据包:CmdNameDescription的长度不固定(而BinaryWriter / BinaryReader通过预先设置字符串的长度来处理此问题。)

相反的是当你有一个固定长度的数据包,有固定长度的字符串。这需要完全不同的处理。