哈喽,好久没写了。
今天分享一个标准库
在C#中把一个struct转换成byte[]输出的方法
直接上代码
public static byte[] StructToBytes(object structObj) { //返回类的非托管大小(以字节为单位) int size = Marshal.SizeOf(structObj); //分配大小 byte[] bytes = new byte[size]; //从进程的非托管堆中分配内存给structPtr IntPtr structPtr = Marshal.AllocHGlobal(size); try { //将数据从托管对象structObj封送到非托管内存块structPtr Marshal.StructureToPtr(structObj, structPtr, false); //Marshal.StructureToPtr(structObj, structPtr, true); //将数据从非托管内存指针复制到托管 8 位无符号整数数组 Marshal.Copy(structPtr, bytes, 0, size); return bytes; } catch (Exception ex) { return null; } finally { //释放以前使用 AllocHGlobal 从进程的非托管内存中分配的内存 Marshal.FreeHGlobal(structPtr); } }
这里使用到了非托管内存,就是自己控制资源开启和释放的区域。
下面在分享一个StructToByte的Helper:
public class ByteHelper { /// <summary> /// 获取取第index位 /// </summary> /// <param name="b"></param> /// <param name="index"></param> /// <returns></returns> public static int GetBit(byte b, int index) { return ((b & (1 << index)) > 0) ? 1 : 0; } /// <summary> /// 将第index位设为1 /// </summary> /// <param name="b"></param> /// <param name="index"></param> /// <returns></returns> public static byte SetBit(byte b, int index) { return (byte)(b | (1 << index)); } /// <summary> /// 将第index位设为0 /// </summary> /// <param name="b"></param> /// <param name="index"></param> /// <returns></returns> public static byte ClearBit(byte b, int index) { return (byte)(b & (byte.MaxValue - (1 << index))); } /// <summary> /// 将第index位取反 /// </summary> /// <param name="b"></param> /// <param name="index"></param> /// <returns></returns> public static byte ReverseBit(byte b, int index) { return (byte)(b ^ (byte)(1 << index)); } /// <summary> /// 将字节A写入目标字节B的指定位 /// </summary> /// <param name="Value">字节B 超过8位时低位数组索引小于高位</param> /// <param name="Index">起始位置</param> /// <param name="Leng">占位长度</param> /// <param name="OriginalValue">A字节</param> /// <returns></returns> public static byte[] BitProcessing(byte[] Value, int Index, int Leng, byte OriginalValue) { bool Med; for (int index = 1; index <= Leng; index++) { byte Weight = (byte)Math.Pow(2, index - 1); Med = ((OriginalValue & Weight) == Weight); int Cursor = Index + index - 1; Value[Cursor / 8] = set_bit(Value[Cursor / 8], Cursor % 8, Med); } return Value; } /// <summary> /// 设置字节任意位 /// </summary> /// <param name="data"></param> /// <param name="index"></param> /// <param name="flag"></param> /// <returns></returns> private static byte set_bit(byte data, int index, bool flag) { ++index; if (index > 8 || index < 1) throw new ArgumentOutOfRangeException(); int v = index < 2 ? index : (2 << (index - 2)); return flag ? (byte)(data | v) : (byte)(data & ~v); } public static byte[] StructToBytes(object structObj) { //返回类的非托管大小(以字节为单位) int size = Marshal.SizeOf(structObj); //分配大小 byte[] bytes = new byte[size]; //从进程的非托管堆中分配内存给structPtr IntPtr structPtr = Marshal.AllocHGlobal(size); try { //将数据从托管对象structObj封送到非托管内存块structPtr Marshal.StructureToPtr(structObj, structPtr, false); //Marshal.StructureToPtr(structObj, structPtr, true); //将数据从非托管内存指针复制到托管 8 位无符号整数数组 Marshal.Copy(structPtr, bytes, 0, size); return bytes; } catch (Exception ex) { return null; } finally { //释放以前使用 AllocHGlobal 从进程的非托管内存中分配的内存 Marshal.FreeHGlobal(structPtr); } } public static object BytesToStruct(byte[] bytes, Type strType) { //获取结构体的大小(以字节为单位) int size = Marshal.SizeOf(strType); //简单的判断(可以去掉) if (size > bytes.Length) { return null; } //从进程的非托管堆中分配内存给structPtr IntPtr strPtr = Marshal.AllocHGlobal(size); try { //将数据从一维托管数组bytes复制到非托管内存指针strPtr Marshal.Copy(bytes, 0, strPtr, size); //将数据从非托管内存块封送到新分配的指定类型的托管对象 //将内存空间转换为目标结构体 object obj = Marshal.PtrToStructure(strPtr, strType); return obj; } catch (Exception ex) { return null; } finally { //释放以前使用 AllocHGlobal 从进程的非托管内存中分配的内存 Marshal.FreeHGlobal(strPtr); } } }ByteHelper
最后顺带说一下,一般看到了我这个文章的都是对Struct进行转换了。别忘记内存对其方式哦
[StructLayout(LayoutKind.Sequential)]
贴在你的Struct类上面,
[StructLayout(LayoutKind.Sequential, Pack = 1)]
pack=1表示标准对其
需要带走