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

虽然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. pycharm Python解释器的配置--可以指定批处理文件为解释器

    这样就可以很方便的配置一些环境变量了,很方便很有创意的功能,再次Mark一下以防忘记

  2. java 中String编码和byte 解码总结——字节流和字符流

    1.InputStreamReader 是字节流通向字符流的桥梁:它使用指定的 charset 读取字节并将其解码为字符 InputStreamReader(InputStream in, Strin ...

  3. JavaScript数据类型 数据转换

    JavaScript数据类型分为两种:原始类型和对象类型,原始类型有:number(数字).string(文本).boolean(布尔值).null(空).undefined(未定义):对象类型有:A ...

  4. LaTeX 修订

    LaTeX多人协同编辑的时候,修订起来与word相比较而言麻烦一些.不过随着技术的发展和需求的增多,会有越来越多的工具支持LaTeX的修订. (1)在线LaTeX ShareLaTeX是一个很优秀的在 ...

  5. 迟到的UED(转发)

    2013UCAN用户体验设计论坛–精彩视频赏析 - 交互设计 博文 视觉设计 | TaoBaoUEDhttp://ued.taobao.org/blog/2013/09/2013ucan/

  6. [Linq To Sql]解决join时的Collation冲突

    背景 现在两表 A:

  7. Stage3--Python控制流程及函数

    说在前面: Stage1-Stage4简单介绍一下Python语法,Stage5开始用python实现一些实际应用,语法的东西到处可以查看到,学习一门程序语言的最终目的是应用,而不是学习语法,语法本事 ...

  8. .NET开源工作流RoadFlow-流程运行-菜单配置

    经过流程设计和表单设计后,一个流程就设置完成了,下面说说怎么让设计好的流程运行起来吧. 流程和表单设计完成发布后都在应用程序库里,我们只要将流程在角色应用中配置给相应的用户即可让流程选择了. 在系统管 ...

  9. sql server中将自增长列归零

    一个项目完成后数据库中会有很多无用的测试数据,可以使用delete * 将数据全部删除,但自增长列(一般是主键)基数不会归零,使用TRUNCATE函数可以将表中数据全部删除,并且将自增长列基数归零.一 ...

  10. 树莓派3(Raspberry pi 3)刷OpenWrt

    原文在 https://my.oschina.net/wangandi/blog/687389 1.下载镜像,这个lede好像是openwrt的一个分支,openwrt本身还没有支持pi3,https ...