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;

 1 /// <summary>
 2 /// 工具类:对象与二进制流间的转换
 3 /// </summary>
 4 class ByteConvertHelper
 5 {
 6     /// <summary>
 7     /// 将对象转换为byte数组
 8     /// </summary>
 9     /// <param name="obj">被转换对象</param>
10     /// <returns>转换后byte数组</returns>
11     public static byte[] Object2Bytes(object obj)
12     {
13         byte[] buff;
14         using (MemoryStream ms = new MemoryStream())
15         {
16             IFormatter iFormatter = new BinaryFormatter();
17             iFormatter.Serialize(ms, obj);
18             buff = ms.GetBuffer();
19         }
20         return buff;
21     }
22 
23     /// <summary>
24     /// 将byte数组转换成对象
25     /// </summary>
26     /// <param name="buff">被转换byte数组</param>
27     /// <returns>转换完成后的对象</returns>
28     public static object Bytes2Object(byte[] buff)
29     {
30         object obj;
31         using (MemoryStream ms = new MemoryStream(buff))
32         {
33             IFormatter iFormatter = new BinaryFormatter();
34             obj = iFormatter.Deserialize(ms);
35         }
36         return obj;
37     }
38 }

调用示例:

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

 1 /// <summary>
 2 /// 测试结构
 3 /// </summary>
 4 [Serializable]
 5 struct TestStructure
 6 {
 7     public string A; //变量A
 8     public char B;   //变量B
 9     public int C;    //变量C
10 
11     /// <summary>
12     /// 构造函数
13     /// </summary>
14     /// <param name="paraA"></param>
15     /// <param name="paraB"></param>
16     /// <param name="paraC"></param>
17     public TestStructure(string paraA, char paraB, int paraC)
18     {
19         this.A = paraA;
20         this.B = paraB;
21         this.C = paraC;
22     }
23 
24     /// <summary>
25     /// 输出本结构中内容
26     /// </summary>
27     /// <returns></returns>
28     public string DisplayInfo()
29     {
30         return string.Format("A:{0};B:{1};C:{2}", this.A, this.B, this.C);
31     }
32 }

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

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

输出为:

 

 需要注意的是,用这个方式进行结构与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

 1 /// <summary>
 2 /// 工具类:对象与二进制流间的转换
 3 /// </summary>
 4 class ByteConvertHelper
 5 {
 6     /// <summary>
 7     /// 将对象转换为byte数组
 8     /// </summary>
 9     /// <param name="obj">被转换对象</param>
10     /// <returns>转换后byte数组</returns>
11     public static byte[] Object2Bytes(object obj)
12     {
13         byte[] buff = new byte[Marshal.SizeOf(obj)];
14         IntPtr ptr = Marshal.UnsafeAddrOfPinnedArrayElement(buff, 0);
15         Marshal.StructureToPtr(obj, ptr, true);
16         return buff;
17     }
18 
19     /// <summary>
20     /// 将byte数组转换成对象
21     /// </summary>
22     /// <param name="buff">被转换byte数组</param>
23     /// <param name="typ">转换成的类名</param>
24     /// <returns>转换完成后的对象</returns>
25     public static object Bytes2Object(byte[] buff, Type typ)
26     {
27         IntPtr ptr = Marshal.UnsafeAddrOfPinnedArrayElement(buff, 0);
28         return Marshal.PtrToStructure(ptr, typ);
29     }
30 }

调用示例:

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

 1 /// <summary>
 2 /// 测试结构
 3 /// </summary>
 4 struct TestStructure
 5 {
 6     public string A; //变量A
 7     public char B;   //变量B
 8     public int C;    //变量C
 9 
10     /// <summary>
11     /// 构造函数
12     /// </summary>
13     /// <param name="paraA"></param>
14     /// <param name="paraB"></param>
15     /// <param name="paraC"></param>
16     public TestStructure(string paraA, char paraB, int paraC)
17     {
18         this.A = paraA;
19         this.B = paraB;
20         this.C = paraC;
21     }
22 
23     /// <summary>
24     /// 输出本结构中内容
25     /// </summary>
26     /// <returns></returns>
27     public string DisplayInfo()
28     {
29         return string.Format("A:{0};B:{1};C:{2}", this.A, this.B, this.C);
30     }
31 }

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

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

运行示例:

 

 

 

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

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

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

 1 /// <summary>
 2 /// 工具类:文件与二进制流间的转换
 3 /// </summary>
 4 class FileBinaryConvertHelper
 5 {
 6     /// <summary>
 7     /// 将文件转换为byte数组
 8     /// </summary>
 9     /// <param name="path">文件地址</param>
10     /// <returns>转换后的byte数组</returns>
11     public static byte[] File2Bytes(string path)
12     {
13         if(!File.Exists(path))
14         {
15             return new byte[0];
16         }
17 
18         FileInfo fi = new FileInfo(path);
19         byte[] buff = new byte[fi.Length];
20 
21         FileStream fs = fi.OpenRead();
22         fs.Read(buff, 0, Convert.ToInt32(fs.Length));
23         fs.Close();
24 
25         return buff;
26     }
27 
28     /// <summary>
29     /// 将byte数组转换为文件并保存到指定地址
30     /// </summary>
31     /// <param name="buff">byte数组</param>
32     /// <param name="savepath">保存地址</param>
33     public static void Bytes2File(byte[] buff, string savepath)
34     {
35         if (File.Exists(savepath))
36         {
37             File.Delete(savepath);
38         }
39 
40         FileStream fs = new FileStream(savepath, FileMode.CreateNew);
41         BinaryWriter bw = new BinaryWriter(fs);
42         bw.Write(buff, 0, buff.Length);
43         bw.Close();
44         fs.Close();
45     }
46 }

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

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

运行结果:

 

 END

转:https://my.oschina.net/Tsybius2014/blog/352409

posted @ 2020-09-03 15:15  X-Jonney  阅读(919)  评论(0编辑  收藏  举报