java marshal 序列化_求教Marshal类实现序列化出现的问题

博主在尝试使用Marshal进行序列化和反序列化时遇到问题,具体表现为:通过StructureToPtr和PtrToStructure方法处理的包含字符串和整型的类对象,在经过TCP Socket传输后,整型字段能够正确反序列化,而字符串字段出现为空或乱码的情况。代码示例中展示了直接序列化和反序列化成功的API实现,以及出现问题的传输过程。问题可能出在编码格式不一致或字符串处理上。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

小弟最近在研究利用Marshal实现序列化和反系列化,主要是使用Marshal类里的两个方法,StructureToPtr和PtrToStructure,这两个类的具体讲解和用法我就不多赘述 了,具体见[url=http://blog.csdn.net/wem520/article/details/9101549][/url],下面说我碰到的问题,我的需求是对一个类的对象通过StructureToPtr序列化成byte[]数组,然后通过TCP Socket传输到另外一个解决方案,再用PtrToStructure反序列化出来这个对象。现在的问题是类的字段类型问题,就是我一个属性是string类型,其余的都是int类型。测试结果发现如果在同一个API里,这个方法能完美实现,但是经过传输再反序列化后int类型可以反序列化出来而string字段就为空或者乱码。小弟百思不得其解,特来求高手帮忙分析解疑。具体代码如下:

API直接序列化反序列化

[code=csharp]

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Runtime.InteropServices;

namespace ConsoleApplication5

{

class Program

{

static void Main(string[] args)

{

Person p = new Person();

p.name = "joseph";

p.age = 18;

p.high = 188;

p.kg = 143;

p.tel = 15689;

byte[] bs = StructToBytes(p);

Person2 py2 = (Person2)BytesToStruct(bs, typeof(Person2));

Console.ReadKey();

}

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]

public class Person

{

public string name { get; set; }

public int age { get; set; }

public int high { get; set; }

public int kg { get; set; }

public int tel { get; set; }

}

//1、struct转换为Byte[]

public static Byte[] StructToBytes(Object structure)

{

Int32 size = Marshal.SizeOf(structure);

IntPtr buffer = Marshal.AllocHGlobal(size);

try

{

Marshal.StructureToPtr(structure, buffer, false);

Byte[] bytes = new Byte[size];

Marshal.Copy(buffer, bytes, 0, size);

return bytes;

}

finally

{

Marshal.FreeHGlobal(buffer);

}

}

//2、Byte[]转换为struct

public static Object BytesToStruct(Byte[] bytes, Type strcutType)

{

Int32 size = Marshal.SizeOf(strcutType);

IntPtr buffer = Marshal.AllocHGlobal(size);

try

{

Marshal.Copy(bytes, 0, buffer, size);

return Marshal.PtrToStructure(buffer, strcutType);

}

finally

{

Marshal.FreeHGlobal(buffer);

}

}

}

}

[/code]

这个方案输出结果完全正确!

下面是我的传输Demon

序列化公共类

[code=csharp]

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Runtime.InteropServices;

using System.IO;

namespace Serialization

{

public class Serializable

{

public static Byte[] StructToBytes(Object structure)

{

Int32 size = Marshal.SizeOf(structure);

IntPtr buffer = Marshal.AllocHGlobal(size);

try

{

Marshal.StructureToPtr(structure, buffer, true);

Byte[] bytes = new Byte[size];

Marshal.Copy(buffer, bytes, 0, size);

return bytes;

}

finally

{

Marshal.FreeHGlobal(buffer);

}

}

//2、Byte[]转换为struct

public static Object BytesToStruct(Byte[] bytes, Type strcutType)

{

Int32 size = Marshal.SizeOf(strcutType);

IntPtr buffer = Marshal.AllocHGlobal(size);

try

{

Marshal.Copy(bytes, 0, buffer, size);

return Marshal.PtrToStructure(buffer, strcutType);

}

catch (Exception ex)

{

return ex.Message;

}

finally

{

Marshal.FreeHGlobal(buffer);

}

}

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode, Pack = 1)]

public class Person

{

public string name { get; set; }

public int age { get; set; }

public int high { get; set; }

public int kg { get; set; }

public int tel { get; set; }

}

}

}

[/code]

下面是调用,分为客户端和服务器,客户端将内容通过Socket传输给服务器(可以看到我中见的一些注释是在尝试编码格式来解决string类型出错)

Client

[code=csharp]

byte[] Data;

Channel channel;

Serializable.Person p;

private void send_Click(object sender, EventArgs e)

{

p = new Serializable.Person();

//byte[] byt = System.Text.UnicodeEncoding.UTF8.GetBytes(name.Text.ToString());

//p.name = System.Text.UnicodeEncoding.UTF8.GetString(byt);

p.name = name.Text.ToString();

p.age = int.Parse(age.Text);

p.high = int.Parse(high.Text);

p.kg = int.Parse(kg.Text);

p.tel = int.Parse(tel.Text);

Data = Serializable.StructToBytes(p);

if (channel != null && Data != null)

{

channel.Send(Data);

Log("发送成功");

}

else

{

Log("数据体为空或信道连接失败");

return;

}

}

[/code]

Server(我只贴出接受数据的方法)

[code=csharp]

public void DataReceive(object sender, ChannelReceiveArg arg)

{

Log("接收到数据" + arg.Data.ToString());

Serializable.Person p = (Serializable.Person)Serializable.BytesToStruct(arg.Data, typeof(Serializable.Person));

name.Text = p.name;

age.Text = p.age.ToString();

high.Text = p.high.ToString();

kg.Text = p.kg.ToString();

tel.Text = p.tel.ToString();

}

[/code]

这个是我的测试,和API思路一样,只是中间多虑步传输,但就是会有各种问题,有时候会在 return Marshal.PtrToStructure(buffer, strcutType);处报这样的错[img=http://img.bbs.csdn.net/upload/201404/01/1396336717_779070.png][/img],有时候运行正常,但是就是那个name出不来。我真是快疯了,求大神啊!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值