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

来源:互联网 发布:什么是ai设计软件 编辑:程序博客网 时间:2024/05/19 02:20
在通信过程中,一般我们都会操作到字节数组.特别是希望在不同语言编程进行操作的时候.
虽然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 );
        
0 0