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

虽然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);
            }
 
        }

C#结构体和字节数组的转换函数的更多相关文章

  1. c#结构体和字节数组的转换、字节数组和stream的转换

    本文由博主(YinaPan)原创,转载请注明出处:http://www.cnblogs.com/YinaPan/p/streambytsstruct.html using System; using ...

  2. c#中关于结构体和字节数组转化

    最近在使用结构体与字节数组转化来实现socket间数据传输.现在开始整理一下.对于Marshal可以查阅msdn,关于字节数组与结构体转代码如下: using System; using System ...

  3. Go -- 中结构体与字节数组能相互转化

    编码时如下,假设默认你的结构体为data func Encode(data interface{}) ([]byte, error) { buf := bytes.NewBuffer(nil) enc ...

  4. 【VS开发】【编程开发】【C/C++开发】结构体中的数组与指针的内存分配情况说明

    [VS开发][编程开发][C/C++开发]结构体中的数组与指针的内存分配情况说明 标签:[VS开发] [编程开发] 主要是疑惑在结构体定义的数组的内存空间与指针动态分配的内存空间,在地址上连续性.以及 ...

  5. c# 调用c++sdk时结构体与byte数组互转

    /// <summary> /// 由结构体转换为byte数组 /// </summary> public static byte[] StructureToByte<T ...

  6. TCP和UDP的区别与联系以及网络字节序和主机字节序的转换函数实践

    TCP和UDP的区别 TCP是一个面向连接的.可靠的.基于字节流的传输层协议. 而UDP是一个面向无连接的传输层协议. 具体来分析,和 UDP 相比,TCP 有三大核心特性: 面向连接:所谓的连接,指 ...

  7. socket编程相关的结构体和字节序转换、IP、PORT转换函数

    注意:结构体之间不能直接进行强制转换, 必须先转换成指针类型才可以进行结构体间的类型转换, 这里需要明确的定义就是什么才叫强制转换. 强制转换是将内存中一段代码以另一种不同类型的方式进行解读, 因此转 ...

  8. c++与C# winform的消息通讯--(结构体与byte数组的使用)

    近期正在做一个蓝牙驱动的使用程序,其中有一块从c++发送数据到C#的部分,网上查了很多资料,大多都是介绍如何通过调用函数获取用户数据.并且在消息发送中,很少介绍如何发送一个结构体,并且结构体里面有 b ...

  9. C语言结构体的字节对齐原则

    为什么要对齐? 现代计算机中内存空间都是按照byte划分的,从理论上讲似乎对任何类型的变量的访问可以从任何地址开始,但实际情况是在访问特定类型变量的时候经常在特 定的内存地址访问,这就需要各种类型数据 ...

随机推荐

  1. 新建maven工程index.jsp页面报错

    引入servlet依赖jar <dependency><groupId>javax.servlet</groupId><artifactId>servl ...

  2. 1分钟搭建极简mock server

    1.无聊的背景.起源: 如今的业务系统越来越复杂庞大,各个功能直接的调用也是多如牛毛,但如果在联调的时候,恰好被调的接口正在开发,怎么办?傻傻的等么,不存在的!这时会搭建一些server来进行mock ...

  3. Windows 那些坑

    Windows Qt搭建 安装Qt 选择MinGW或者MSVC(建议VC), qt自动检测编译器, 基本上不用配置 去掉UWP(Windows通用平台开始, 不同于传统的exe, 它可以运行在所有的W ...

  4. nyoj 568——RMQ with Shifts——————【线段树单点更新、区间求最值】

    RMQ with Shifts 时间限制:1000 ms  |  内存限制:65535 KB 难度:3   描述     In the traditional RMQ (Range Minimum Q ...

  5. 认识Spring AOP

    Spring AOP AOP是Aspect/'æspekt/ Oriented/ɔːrɪentɪd/ Programming的缩写,意为:面向切面编程. 是什么 通过预编译方式和运行期动态代理实现程序 ...

  6. k-近邻算法(kNN)

    1.算法工作原理 存在一个训练样本集,我们知道样本集中的每一个数据与所属分类的对应关系,输入没有标签的新数据后,将新数据的每个特征与样本集中数据对应特征进行比较,然后算法提取样本集中特征最相似的数据( ...

  7. scope 作用域(bean 的生存范围)

    默认是 singleton ,单例模式,如下代码: @Test public void testAddUser() throws Exception { ApplicationContext ctx ...

  8. 订阅无法在 ARM 模式下创建虚拟机,只能在 ASM 模式下创建 Azure VM 部署

    问题描述 资源组所有者可以在新版 portal 创建经典模式的虚拟机,但是无法创建 ARM 模式的虚拟机. 问题现象 环境中有个相对权限比较高的账户,比如 account admin (以下简称为 A ...

  9. SQL Server ->> 重命名数据库

    ALTER DATABASE [oldDB] SET SINGLE_USER WITH ROLLBACK IMMEDIATE GO ALTER DATABASE [oldDB] MODIFY NAME ...

  10. 如何用css将一个div设置为一个圆

    直接上代码: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> ...