C# 对象、文件与二进制串(byte数组)之间的转换

来源:互联网 发布:智能对话机器人软件 编辑:程序博客网 时间:2024/06/11 13:24

C# 对象、文件与二进制串(byte数组)之间的转换

1.关于本文

在使用C#下的TCP(类TcpClient)、UDP(类UdpClient)协议传输信息时,都需要将信息转换为byte类型的数组进行发送。本文实现了两种object与byte数组的转换和一种文件与byte数组转换的方式。基础类型的数据,可以用BitConverter类中的函数进行转换。

2.object与byte[]的相互转换:使用IFormatter的Serialize和Deserialize进行序列化与反序列化

实现这个功能,需要先引用三个命名空间:System.IO、System.Runtime.Serialization、System.Runtime.Serialization.Formatters.Binary;

/// <summary>/// 工具类:对象与二进制流间的转换/// </summary>class ByteConvertHelper{  /// <summary>  /// 将对象转换为byte数组  /// </summary>  /// <param name="obj">被转换对象</param>  /// <returns>转换后byte数组</returns>  public static byte[] Object2Bytes(object obj)  {    byte[] buff;    using (MemoryStream ms = new MemoryStream())    {      IFormatter iFormatter = new BinaryFormatter();      iFormatter.Serialize(ms, obj);      buff = ms.GetBuffer();    }    return buff;  }  /// <summary>  /// 将byte数组转换成对象  /// </summary>  /// <param name="buff">被转换byte数组</param>  /// <returns>转换完成后的对象</returns>  public static object Bytes2Object(byte[] buff)  {    object obj;    using (MemoryStream ms = new MemoryStream(buff))    {      IFormatter iFormatter = new BinaryFormatter();      obj = iFormatter.Deserialize(ms);    }    return obj;  }}

调用示例:

假设有一个添加了Serializable特性的结构:

/// <summary>/// 测试结构/// </summary>[Serializable]struct TestStructure{  public string A; //变量A  public char B;   //变量B  public int C;//变量C  /// <summary>  /// 构造函数  /// </summary>  /// <param name="paraA"></param>  /// <param name="paraB"></param>  /// <param name="paraC"></param>  public TestStructure(string paraA, char paraB, int paraC)  {    this.A = paraA;    this.B = paraB;    this.C = paraC;  }  /// <summary>  /// 输出本结构中内容  /// </summary>  /// <returns></returns>  public string DisplayInfo()  {    return string.Format("A:{0};B:{1};C:{2}", this.A, this.B, this.C);  }}

那么调用下面的代码可以完成这个结构的转换

static void Main(string[] args){  TestStructure tsA = new TestStructure("1234", '5', 6);  byte[] bytTemp = ByteConvertHelper.Object2Bytes(tsA);  Console.WriteLine("数组长度:" + bytTemp.Length);  TestStructure tsB = (TestStructure)ByteConvertHelper.Bytes2Object(bytTemp);  Console.WriteLine(tsB.DisplayInfo());  Console.ReadLine();}

输出为:

需要注意的是,用这个方式进行结构与byte数组间的转换,结构或类必须有Serializable特性。否则会有异常(SerializationException):“程序集 “XXX, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null” 中的类型 “XXX.XXX” 未标记为可序列化”

另外,这个方式生成的byte数组长度较大

3.使用Marshal类的StructureToPtr与PtrToStructure函数对object与byte数组进行转换

实现这个功能,需要先引用命名空间:System.Runtime.InteropServices

/// <summary>/// 工具类:对象与二进制流间的转换/// </summary>class ByteConvertHelper{  /// <summary>  /// 将对象转换为byte数组  /// </summary>  /// <param name="obj">被转换对象</param>  /// <returns>转换后byte数组</returns>  public static byte[] Object2Bytes(object obj)  {    byte[] buff = new byte[Marshal.SizeOf(obj)];    IntPtr ptr = Marshal.UnsafeAddrOfPinnedArrayElement(buff, 0);    Marshal.StructureToPtr(obj, ptr, true);    return buff;  }  /// <summary>  /// 将byte数组转换成对象  /// </summary>  /// <param name="buff">被转换byte数组</param>  /// <param name="typ">转换成的类名</param>  /// <returns>转换完成后的对象</returns>  public static object Bytes2Object(byte[] buff, Type typ)  {    IntPtr ptr = Marshal.UnsafeAddrOfPinnedArrayElement(buff, 0);    return Marshal.PtrToStructure(ptr, typ);  }}

调用示例:

现有结构如下(就是比上面示例中的结构少了特性Serializable):

/// <summary>/// 测试结构/// </summary>struct TestStructure{  public string A; //变量A  public char B;   //变量B  public int C;//变量C  /// <summary>  /// 构造函数  /// </summary>  /// <param name="paraA"></param>  /// <param name="paraB"></param>  /// <param name="paraC"></param>  public TestStructure(string paraA, char paraB, int paraC)  {    this.A = paraA;    this.B = paraB;    this.C = paraC;  }  /// <summary>  /// 输出本结构中内容  /// </summary>  /// <returns></returns>  public string DisplayInfo()  {    return string.Format("A:{0};B:{1};C:{2}", this.A, this.B, this.C);  }}

调用下面的代码可以完成转换:

static void Main(string[] args){  TestStructure tsA = new TestStructure("1234", '5', 6);  byte[] bytTemp = ByteConvertHelper.Object2Bytes(tsA);  Console.WriteLine("数组长度:" + bytTemp.Length);  TestStructure tsB = (TestStructure)ByteConvertHelper.Bytes2Object(    bytTemp, Type.GetType("ByteConverter2.TestStructure"));  Console.WriteLine(tsB.DisplayInfo());  Console.ReadLine();}

运行示例:

可以看到,数组长度仅为12,比上面示例中转换的byte[]数组短了非常多,更加节省空间

3.使用FileStream将文件与byte数组相互转换

实现这个功能,需要先引用命名空间:System.IO

/// <summary>/// 工具类:文件与二进制流间的转换/// </summary>class FileBinaryConvertHelper{  /// <summary>  /// 将文件转换为byte数组  /// </summary>  /// <param name="path">文件地址</param>  /// <returns>转换后的byte数组</returns>  public static byte[] File2Bytes(string path)  {    if(!File.Exists(path))    {      return new byte[0];    }    FileInfo fi = new FileInfo(path);    byte[] buff = new byte[fi.Length];    FileStream fs = fi.OpenRead();    fs.Read(buff, 0, Convert.ToInt32(fs.Length));    fs.Close();    return buff;  }  /// <summary>  /// 将byte数组转换为文件并保存到指定地址  /// </summary>  /// <param name="buff">byte数组</param>  /// <param name="savepath">保存地址</param>  public static void Bytes2File(byte[] buff, string savepath)  {    if (File.Exists(savepath))    {      File.Delete(savepath);    }    FileStream fs = new FileStream(savepath, FileMode.CreateNew);    BinaryWriter bw = new BinaryWriter(fs);    bw.Write(buff, 0, buff.Length);    bw.Close();    fs.Close();  }}

假设有文件test.txt,调用下面代码可以将test.txt写到byte数组中,并将这个byte数组的内容写入到文件output.txt里

static void Main(string[] args){  byte[] bytTemp = FileBinaryConvertHelper.File2Bytes("test.txt");  Console.WriteLine("数组长度:" + bytTemp.Length);  FileBinaryConvertHelper.Bytes2File(bytTemp, "output.txt");  Console.WriteLine("输出完成");  Console.ReadLine();}

运行结果:

END

0 0
原创粉丝点击