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

虽然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. Linux 下安装 Memcached 和 PHP 开启 Memcached 扩展 及 LAMP 环境的安装

    http://blog.csdn.net/liruxing1715/article/details/8269563

  2. React.js 小书 Lesson8 - 组件的组合、嵌套和组件树

    作者:胡子大哈 原文链接:http://huziketang.com/books/react/lesson8 转载请注明出处,保留原文链接和作者信息. 继续拓展前面的例子,现在我们已经有了 Heade ...

  3. xss攻击汇总--转

    (1)普通的XSS JavaScript注入<SCRIPT SRC=http://3w.org/XSS/xss.js></SCRIPT>(2)IMG标签XSS使用JavaScr ...

  4. PCU

    PCU(Peak concurrent users ),互联网术语,应用在网络游戏和其他互联网服务领域,意思是最高同时在线人数 业务系统架构性能提升主要分为两种不同的方式,scale-out(横向扩展 ...

  5. 【C#.NET】Http Handler 介绍---(转)

    Http Handler 介绍 引言 在 Part.1 Http请求处理流程 一文中,我们了解了Http请求的处理过程以及其它一些运作原理.我们知道Http管道中有两个可用接口,一个是IHttpHan ...

  6. jdbc封装DBUtil

    1.编写实体类User public class User { private Integer id; private String username; private Integer age; pr ...

  7. Mysql性能调优方法

    第一种方法 1.选取最适用的字段属性 MySQL可以很好的支持大数据量的存取,但是一般说来,数据库中的表越小,在它上面执行的查询也就会越快.因此,在创建表的时候,为了获得更好的 性能,我们可以将表中字 ...

  8. hook_myhook.api.php文件什么用

    看源文件的时候发现有个user.api.php文件,里面定义了一个新的钩子,$hook_user_categories,但是,drupal核心里面没有,我推测是自定义 的钩子函数,然后在*.modul ...

  9. PHP性能检测与优化—XHProf 安装

    PHP性能检测与优化—XHProf 安装 XHProf是facebook开源出来的一个php轻量级的性能分析工具,跟Xdebug类似,但性能开销更低,还可以用在生产环境中,也可以由程序开关来控制是否进 ...

  10. 常用css属性记录

    CSS常用属性: 字体属性:(font)大小 font-size: x-large;(特大) xx-small;(极小) 一般中文用不到,只要用数值就可以,单位:PX.PD样式 font-style: ...