zoukankan      html  css  js  c++  java
  • 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);
                }
     
            }
  • 相关阅读:
    AOP与IOC的概念(即spring的核心)
    Md5密码加密的使用
    all-mobile.js
    config.js
    login.css
    template.css
    index.js
    view.js
    admin.css
    admin.js
  • 原文地址:https://www.cnblogs.com/dj1232090/p/5720001.html
Copyright © 2011-2022 走看看