前段时间测试一个P2P程序,通过UDP来发送数据。UdpClient.Send(..)方法需要一个byte[]这样的参数。想当年用c++Builder的时候,只需要用强制转换就行了。如今时过境迁,.net平台上处理这事却似乎有些麻烦!今天恰好在csdn上见一帖,又看到了另一种处理方法,^_^, 现将我所知的3种方法总结一下。
一、通过序列化将对象转为byte[], 之后再反序化为对象
public
class
P2PHelper
{ /**//// <summary>
/// 将一个object对象序列化,返回一个byte[]
/// </summary>
/// <param name="obj">能序列化的对象</param>
/// <returns></returns>
public static byte[] ObjectToBytes(object obj)
{
using (MemoryStream ms = new MemoryStream())
{
IFormatter formatter = new BinaryFormatter();
formatter.Serialize(ms, obj);
return ms.GetBuffer();
}
}

/**//// <summary>
/// 将一个序列化后的byte[]数组还原
/// </summary>
/// <param name="Bytes"></param>
/// <returns></returns>
public static object BytesToObject(byte[] Bytes)
{
using (MemoryStream ms = new MemoryStream(Bytes))
{
IFormatter formatter = new BinaryFormatter();
return formatter.Deserialize(ms);
}
}
}
二、使用BitConvert类来处理
很麻烦的一种方法,我这等懒人是不敢用这种方法的了。不过这篇文章 http://pierce.cnblogs.com/archive/2005/06/21/178343.aspx 上有些讲解,想了解的朋友可以去看看。
三、使用Unsafe方式
先看代码(尚不知是否有memory leak!!!):
class
Test
{
public static unsafe byte[] Struct2Bytes(Object obj)
{
int size = Marshal.SizeOf(obj);
byte[] bytes = new byte[size];
fixed(byte* pb = &bytes[0])
{
Marshal.StructureToPtr(obj,new IntPtr(pb),true);
}
return bytes;
}
public static unsafe Object Bytes2Struct(byte[] bytes)
{
fixed(byte* pb = &bytes[0])
{
return Marshal.PtrToStructure(new IntPtr(pb), typeof(Data));
}
}
}
倘若还有其它方法,请告之,:)
评论:
但使用BitConvert类来处理会更简单.
然后每一个对象序列化后都至少有1K, 会导致网络流量的增大。想想,如果一个对象只有10个字节,然而发送的时候却有1K~~~~~~恐怖
对此我非常质疑。如果对象真的只占10个字节的话,肯定只有256字节。BinaryFormatter使用空间是成倍增长的,当实际占用需要大于256字节时,为512字节;当实际占用需要大于512字节时,为1024字节;然后是2048、4096....依次类推。
除了一个文本的用于描述程序集名、类型名和字段名的内容外,所占用的空间是实际所需的。
如果楼主想节省字节,有两个方案:
最好的方法是采用标准的压缩方式将内容压缩,一般会非常小,甚至可能比实际占用的空间还要小。网上有大量开源的压缩类库可以使用。
如果嫌这个方法麻烦,有个方法更易于实现。就是数一数尾部有多少个0,清除这些0,补上一个字节的空间,写上多少个零就行了。不过这种方式省不了多少字节。
我已经不知道如何说服你了。你可不可以相信MS的程序员都不是傻瓜?在Remoting中大量用到Serialization,难道他们从来不考虑减少网络流量的问题?
using System;
using System.Collections;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
[Serializable]
public class MyClass
{
private string _Value;
public string Value
{
get
{
return _Value;
}
set
{
_Value = value;
}
}
public static void Main()
{
int[] lens = new int[] {100, 800, 1000, 3000, 6000, 10000};
MyClass myClass = new MyClass();
foreach (int len in lens)
{
myClass.Value = new string('z', len);
byte[] buff = ObjectToBytes(myClass);
WL("Field Length: {0}, Buffer Length: {1}", len, buff.Length);
}
RL();
}
public static byte[] ObjectToBytes(object obj)
{
using (MemoryStream ms = new MemoryStream())
{
IFormatter formatter = new BinaryFormatter();
formatter.Serialize(ms, obj);
return ms.GetBuffer();
}
}
{
Console.WriteLine(text, args);
}
private static void RL()
{
Console.ReadLine();
}
private static void Break()
{
System.Diagnostics.Debugger.Break();
}
}
Field Length: 800, Buffer Length: 1024
Field Length: 1000, Buffer Length: 2048
Field Length: 3000, Buffer Length: 4096
Field Length: 6000, Buffer Length: 8192
Field Length: 10000, Buffer Length: 16384
using (MemoryStream ms = new MemoryStream())
{
IFormatter formatter = new BinaryFormatter();
formatter.Serialize(ms, obj);
ms.Seek(0, SeekOrigin.Begin);
byte[] buffer = new byte[(int)ms.Length];
ms.Read(buffer, 0, buffer.Length);
ms.Close();
return buffer;
}
本文展示了如何在C#中利用BinaryFormatter将一个可序列化的类对象`MyClass`转换成字节数组。通过创建一个实例,设置其属性,并通过`ObjectToBytes`方法进行序列化,生成的字节数组长度与对象字段的长度有关。这个过程对于通过socket传输对象数据至关重要。
707

被折叠的 条评论
为什么被折叠?



