C#结构体和字节数组的转换函数


在通信过程中,一般我们都会操作到字节数组.特别是希望在不同语言编程进行操作的时候.

虽然C#提供了序列化的支持,不用字节数组也行.但操作字节数组肯定会碰到.
 
一般都会采用结构来表示字节数组.但结构与字节数组直接的转换实在很麻烦.
字节操作不但容易出错,而且每增加一个结构,就自己实现一遍,实在是烦不胜烦.
 
有没有简单的方法呢?当然有.可以采用非托管区的一些方法来实现.
 
首先,导入命名空间:System.Runtime.InteropServices;
 
定义结构的时候,要给结构指定特性.
 
如:
     //注意这个特性不能少
     [StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
     struct TestStruct
     {
         public int c;
         //字符串,SizeConst为字符串的最大长度
         [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
         public string str;
         //int数组,SizeConst表示数组的个数,在转换成
         //byte数组前必须先初始化数组,再使用,初始化
         //的数组长度必须和SizeConst一致,例test = new int[6];
         [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)]
         public int[] test;
        
     }
 
你可以修改特性的属性,来更改在内存的布局和排列.
 
好,接下来将结果转换为字节数据.为了支持各种结构,我采用泛型的做法.这样编译器可以帮助我们检查类型是否正确.
 
   ///
         /// 结构体转byte数组
         ///
         /// 要转换的结构体
         /// 转换后的byte数组
         public static byte[] StructToBytes(T structObj)where T:struct
         {
             //得到结构体的大小
             int size = Marshal.SizeOf(structObj);
             //创建byte数组
             byte[] bytes = new byte[size];
             //分配结构体大小的内存空间
             IntPtr structPtr = Marshal.AllocHGlobal(size);
             //将结构体拷到分配好的内存空间
             Marshal.StructureToPtr(structObj, structPtr, false);
             //从内存空间拷到byte数组
             Marshal.Copy(structPtr, bytes, 0, size);
             //释放内存空间
             Marshal.FreeHGlobal(structPtr);
             //返回byte数组
             return bytes;
         }
 
将字节数组转换为指定结构
 
         ///
         /// byte数组转结构体
         ///
         /// byte数组
         /// 转换后的结构体
         public static T BytesToStuct(byte[] bytes)where T:struct
         {
             T type = new T();
             
             //得到结构体的大小
             int size = Marshal.SizeOf(type);
             //byte数组长度小于结构体的大小
             if (size > bytes.Length)
             {
                 //返回空
                 return (default (T));
             }
             //分配结构体大小的内存空间
             IntPtr structPtr = Marshal.AllocHGlobal(size);
             //将byte数组拷到分配好的内存空间
             Marshal.Copy(bytes,0,structPtr,size);
             //将内存空间转换为目标结构体
             object obj = Marshal.PtrToStructure(structPtr, type.GetType ());
             //释放内存空间
             Marshal.FreeHGlobal(structPtr);
             //返回结构体
             return (T)obj;
         }
 
虽然我对T类型进行了限制,但如果结构没有指定特性的话,运行不会出现问题,但逻辑可能会出现一些问题,出现了你不想要的结果.这是必须注意的.
 
那怎么使用这些代码呢?
 
         public static void TestC()
         {
             TestStruct t = new TestStruct();
             t.c = 100;
             t.str = "12345";
             t.test = new int[] { 1, 2, 5, 6, 9,4 };
 
             byte[] data = StructToBytes(t);
             foreach (var item in data)
             {
                 Console.WriteLine(item);
             }
 
             TestStruct tm = BytesToStuct(data);
 
             Console.WriteLine("C:{0} str={1}",tm.c,tm.str );
             foreach (var item in tm.test)
             {
                 Console.WriteLine(item);
             }
 
         }


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM